Hola a todos, soy nuevo en el mundo de delphi y quisiera q alguien me pudira ayudar a crear un pequeño chat multicliente en delphi7
q es lo q tengo acceso hasta el momento.
Escrito 18 noviembre 2016 - 11:08
Hola a todos, soy nuevo en el mundo de delphi y quisiera q alguien me pudira ayudar a crear un pequeño chat multicliente en delphi7
q es lo q tengo acceso hasta el momento.
Escrito 18 noviembre 2016 - 11:38
Hola, ¿el Chat sería en un Intranet ó Internet?.
Escrito 18 noviembre 2016 - 11:44
Es para intranet par una red pequeña
Escrito 18 noviembre 2016 - 12:06
Puedes empezar con los componentes Indy, en su página de ejemplos en el apartado de The 'old' indy demos hay un demo de Chat empieza con eso y avisas cualquier problema y te ayudaremos.
Saludos.
Escrito 22 noviembre 2016 - 01:02
Puedes empezar con los componentes Indy, en su página de ejemplos en el apartado de The 'old' indy demos hay un demo de Chat empieza con eso y avisas cualquier problema y te ayudaremos.
Saludos.
Muchisimas gracias ya e logrado casi mi primer chat
Pero estoy usando indy9 y cuando corro el codigo y cierro el servidor del chat con alguin conetado me da un error, trate de desconctarlos a todos antes de cerrar y me sige dando el mismo error, cuando compino me pincha bien pero no se si en un futoro sera un problema.
Escrito 22 noviembre 2016 - 01:40
¿Cual es el error?.
Escrito 23 noviembre 2016 - 07:35
Project raised exception class EIdNotConnected with message 'Not Connected'.Process stopped. Used Step or Run to Contunue.
Escrito 23 noviembre 2016 - 07:36
ademas como puedo hacer q el cliente se me quede escuchado lo q mande el server sin congelar la interfas.
Escrito 23 noviembre 2016 - 09:17
Project raised exception class EIdNotConnected with message 'Not Connected'.Process stopped. Used Step or Run to Contunue.
La unica forma de que podamos intentar "depurar" la aplicacion es con codigo y linea de error que genero la excepcion. Te recomiendo que busques y aprendas a depurar tus programas
ademas como puedo hacer q el cliente se me quede escuchado lo q mande el server sin congelar la interfas.
Tenes que crear un hilo que se ejecuta en background y es el que se encarga de escuchar los mensajes. Cuando llega algo, le "avisa" al hilo principal para que actualice la interfaz grafica. Busca sobre multithreading
Escrito 23 noviembre 2016 - 10:34
ya cree el hilo pero el problema ahora es q cuando el cliente se desconecta no se puede volver a conectar me dice q no se puede asignar el socket "cannot allocate socket" sin embargo el idTCPClinet me detecta q a sido desconectado del server pero no me libera el socket, intente liberarlo manual pero no me sirvio, cuado el dectacta q se deconeto mando a para el hilo, no se si lo estare haciendo bien este codigo lo qestrage de otro ejemplo q subieron aki
function ThClient(Param: Pointer): DWORD; stdcall; begin Client; Result:= 0; end; procedure StopClient; begin Terminated:= true; WSACleanup; WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); end; procedure StartThClient; begin hThread:= CreateThread(nil, 0, @ThClient, nil, 0, ThreadId); end;
con esto es con lo q inicio y paro el hilo
Escrito 23 noviembre 2016 - 10:59
Veo que tienes un servidor con indy y un cliente a bajo nivel basado en lo que te mostré aquí.
En TCP tanto cliente como servidor crean un Socket de comunicación tras la conexión. Al perder la conexión ambos deben cerrar el socket. El cliente deberá repetir su proceso al reconectar y es fundamental que inicie la librería winsock si se cerró:
WSAStartup(MAKEWORD(2, 0), Wsa)
Habrá que ver cual es el código del cliente y que le impide reconectar. Y si el error esta del lado del cliente o del servidor.
Por otro lado, TCP puede manejarse con bloqueo o sin él. Si se usa con bloqueo hay que crear hilos en el servidor. Generalmente esa tarea la hacen los componentes cuando se usan éstos. A bajo nivel los tienes que crear y controlar tu. El cliente solo precisa de un hilo. El ejemplo que puse usa el modo con bloqueo, pero con un outoftime de 1000 ms.
Saludos.
Escrito 23 noviembre 2016 - 11:40
ese error me dio con un cliente con indy que le implemente lo q uste me enseño, el error es del cliente pus e probado el server con los clientes q hay en los ejemplos de indy9 y pincha bacan pero a la hora de implementarle la funcion para los hilo es q aparece el error me envia para la linea de idTCPClient.Conect;
Escrito 23 noviembre 2016 - 11:46
El cliente debe contener en su bucle toda la comunicación.
Saludos.
Escrito 23 noviembre 2016 - 12:07
subo el cliente pa q lo vean completo ya a mi se me tosto el celebro jajajaj
Unit del Cliente
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, jpeg, ExtCtrls, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,ThreadCliente; type TForm1 = class(TForm) Image1: TImage; Label1: TLabel; edtHost: TEdit; Label2: TLabel; edtPortG: TEdit; Label3: TLabel; edtPort: TEdit; Label4: TLabel; edtUser: TEdit; Label5: TLabel; edtPass: TEdit; CheckBox1: TCheckBox; Button1: TButton; Button2: TButton; IdTCPClient: TIdTCPClient; procedure Button1Click(Sender: TObject); procedure IdTCPClientConnected(Sender: TObject); procedure Button2Click(Sender: TObject); procedure IdTCPClientDisconnected(Sender: TObject); private { Private declarations } public procedure LockControls(ALock: Boolean); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.LockControls(ALock: Boolean); var i : integer; begin for i := 0 to componentcount-1 do if TControl(Components[i]).Tag = 99 then TControl(Components[i]).Enabled := ALock; end; procedure TForm1.Button1Click(Sender: TObject); begin IdTCPClient.Host:= edtHost.Text; IdTCPClient.Port:= StrToInt(edtPort.Text); if IdTCPClient.Connected then IdTCPClient.Disconnect; IdTCPClient.Connect; { with IdTCPClient do begin Host := edtHost.Text; Port := StrToint(edtPort.Text); try Connect; // add a timeout here if you wish, eg: Connect(3000) = timeout after 3 seconds. // LockControls(False); except on E : Exception do begin LockControls(True); ShowMessage(E.Message); end; end; end; } end; procedure TForm1.IdTCPClientConnected(Sender: TObject); begin IdTCPClient.WriteLn('@Login|'+ edtUser.Text + '|' + edtPass.Text); StartThClient; end; procedure TForm1.Button2Click(Sender: TObject); begin Close; end; procedure TForm1.IdTCPClientDisconnected(Sender: TObject); begin StopClient; end; end.
Donde ejecuto el hilo para la escucha
unit ThreadCliente; interface uses SysUtils, Windows,Dialogs, Messages, SharedMemory, USend, ComCtrls, winsock; procedure Client; procedure StopClient; procedure StartThClient; procedure ComanLogin(msg:String); function GetToken(aString, SepChar: string; TokenNum: Byte): string; var Memory: TSharedMemory; Terminated: BOOL = false; ThreadId: DWORD = 0; hThread: THANDLE = 0; implementation uses Unit1, IdTCPConnection; function GetToken(aString, SepChar: string; TokenNum: Byte): string; var Token: string; StrLen: Integer; Num: Integer; EndofToken: Integer; begin StrLen := Length(aString); Num := 1; EndofToken := StrLen; while ((Num <= TokenNum) and (EndofToken <> 0)) do begin EndofToken := Pos(SepChar, aString); if EndofToken <> 0 then begin Token := Copy(aString, 1, EndofToken - 1); Delete(aString, 1, EndofToken); Inc(Num); end else Token := aString; end; if Num >= TokenNum then Result := Token else Result := ''; end; procedure ComanLogin(msg:String); begin msg:= UpperCase(msg); //if msg= 'OK' then // if msg= 'BANIADO' then ShowMessage('Usuario Baniado'); // if msg= 'USERPASS' then ShowMessage('Usuario o contraseña incorrecta.'); end; Procedure Client; var RText,Com: String; begin repeat RText:= Form1.IdTCPClient.ReadLn; Form1.edtUser.Text := GetToken(RText,'|',2); Com:= GetToken(RText,'|',1); if UpperCase(Com) ='@LOGIN' then ComanLogin(GetToken(RText,'|',2)); until Terminated; Form1.IdTCPClient.Disconnect; WSACleanup; end; function ThClient(Param: Pointer): DWORD; stdcall; begin Client; Result:= 0; end; procedure StopClient; begin Terminated:= true; WSACleanup; WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); end; procedure StartThClient; begin hThread:= CreateThread(nil, 0, @ThClient, nil, 0, ThreadId); end; end.
Escrito 23 noviembre 2016 - 12:10
Esto es lo q avia logrado por esta via hasta ahora pero no se como meter toda la comunicacion en el otro hilo
Escrito 23 noviembre 2016 - 04:56
Estas mezclando un cliente indy con manejo a bajo nivel otro a bajo nivel de socket como WSACleanup. No debes cerrar la librería Winsock pues eso lo hará indy cuanto le toque. Revisa los ejemplos que te proporcionó enecumene donde muestran como enviar y recibir. En una app con este tipo de componentes no debes mezclar alto y bajo nivel si no sabes exactamente lo que haces.
También puedes optar por componentes nativos VCL como TcpServer y TcpClient que te permiten usar socket bloqueados o no. Revisa los métodos ReceiveFrom, SendTo y el evento OnReceive. Quizás te resulte más familiar.
También puedes optar por TClientSocket y TServerSocket que ta dan un nivel más bajo de programación.
Personalmente prefiero no usar componentes para estas cosas. Prefiero los sockets a bajo nivel pues tienes un control muy preciso de ellos.
Saludos.
Escrito 23 noviembre 2016 - 07:23
Estas imágenes te muestran como crear una comunicación simple a bajo nivel cliente-servisor y otra a base de threads con varios clientes:
Saludos.
Escrito 28 noviembre 2016 - 03:31
Muchisimas grasias por las clases e adelantado un mundo
ya tengo logrado la comunicacion cliente/servidor, el problema ahora es a la hora de parar el server con usuarios conectados, encontre un tema en el cual al parecer tenia mi mismo problema y lo resolvio pero no puso la respuesta http://delphiaccess....server-de-indy/
Escrito 28 noviembre 2016 - 04:44
Y no te funciona el TidTCPConnection.disconnect?, Utiliza el evento OnDisconnect para manejar cualquier error.
Saludos.