Ir al contenido


Foto

Mi primer Chat


  • Por favor identifícate para responder
18 respuestas en este tema

#1 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

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.


  • 0

#2 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.409 mensajes
  • LocationRepública Dominicana

Escrito 18 noviembre 2016 - 11:38

Hola, ¿el Chat sería en un Intranet ó Internet?.


  • 0

#3 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

Escrito 18 noviembre 2016 - 11:44

Es para intranet par una red pequeña


  • 0

#4 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.409 mensajes
  • LocationRepública Dominicana

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.


  • 0

#5 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

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.


  • 0

#6 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.409 mensajes
  • LocationRepública Dominicana

Escrito 22 noviembre 2016 - 01:40

¿Cual es el error?.


  • 0

#7 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

Escrito 23 noviembre 2016 - 07:35

Project raised exception class EIdNotConnected with message 'Not Connected'.Process stopped. Used Step or Run to Contunue.


  • 0

#8 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

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.


  • 0

#9 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

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


  • 0

#10 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

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


delphi
  1. function ThClient(Param: Pointer): DWORD; stdcall;
  2. begin
  3. Client;
  4. Result:= 0;
  5. end;
  6.  
  7. procedure StopClient;
  8. begin
  9. Terminated:= true;
  10. WSACleanup;
  11. WaitForSingleObject(hThread, INFINITE);
  12. CloseHandle(hThread);
  13. end;
  14.  
  15. procedure StartThClient;
  16. begin
  17. hThread:= CreateThread(nil, 0, @ThClient, nil, 0, ThreadId);
  18. end;

con esto es con lo q inicio y paro el hilo


  • 0

#11 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 4.014 mensajes
  • LocationMadrid - España

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ó:


delphi
  1. 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.


  • 2

#12 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

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;


  • 0

#13 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 4.014 mensajes
  • LocationMadrid - España

Escrito 23 noviembre 2016 - 11:46

El cliente debe contener en su bucle toda la comunicación.

 

Saludos.


  • 0

#14 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

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


delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, jpeg, ExtCtrls, StdCtrls, IdBaseComponent, IdComponent,
  8. IdTCPConnection, IdTCPClient,ThreadCliente;
  9.  
  10. type
  11. TForm1 = class(TForm)
  12. Image1: TImage;
  13. Label1: TLabel;
  14. edtHost: TEdit;
  15. Label2: TLabel;
  16. edtPortG: TEdit;
  17. Label3: TLabel;
  18. edtPort: TEdit;
  19. Label4: TLabel;
  20. edtUser: TEdit;
  21. Label5: TLabel;
  22. edtPass: TEdit;
  23. CheckBox1: TCheckBox;
  24. Button1: TButton;
  25. Button2: TButton;
  26. IdTCPClient: TIdTCPClient;
  27. procedure Button1Click(Sender: TObject);
  28. procedure IdTCPClientConnected(Sender: TObject);
  29. procedure Button2Click(Sender: TObject);
  30. procedure IdTCPClientDisconnected(Sender: TObject);
  31.  
  32. private
  33. { Private declarations }
  34. public
  35. procedure LockControls(ALock: Boolean);
  36. end;
  37.  
  38. var
  39. Form1: TForm1;
  40.  
  41. implementation
  42.  
  43. {$R *.dfm}
  44.  
  45.  
  46.  
  47. procedure TForm1.LockControls(ALock: Boolean);
  48. var
  49. i : integer;
  50. begin
  51. for i := 0 to componentcount-1 do
  52. if TControl(Components[i]).Tag = 99 then
  53. TControl(Components[i]).Enabled := ALock;
  54. end;
  55. procedure TForm1.Button1Click(Sender: TObject);
  56. begin
  57.  
  58. IdTCPClient.Host:= edtHost.Text;
  59. IdTCPClient.Port:= StrToInt(edtPort.Text);
  60. if IdTCPClient.Connected then IdTCPClient.Disconnect;
  61. IdTCPClient.Connect;
  62. {
  63. with IdTCPClient do
  64.   begin
  65.   Host := edtHost.Text;
  66.   Port := StrToint(edtPort.Text);
  67.   try
  68.   Connect; // add a timeout here if you wish, eg: Connect(3000) = timeout after 3 seconds.
  69.  
  70. // LockControls(False);
  71.  
  72.   except
  73.   on E : Exception do
  74.   begin
  75.   LockControls(True);
  76.   ShowMessage(E.Message);
  77.   end;
  78.   end;
  79.   end;
  80.   }
  81. end;
  82.  
  83. procedure TForm1.IdTCPClientConnected(Sender: TObject);
  84. begin
  85. IdTCPClient.WriteLn('@Login|'+ edtUser.Text + '|' + edtPass.Text);
  86. StartThClient;
  87. end;
  88.  
  89. procedure TForm1.Button2Click(Sender: TObject);
  90. begin
  91. Close;
  92. end;
  93.  
  94. procedure TForm1.IdTCPClientDisconnected(Sender: TObject);
  95. begin
  96. StopClient;
  97.  
  98. end;
  99.  
  100.  
  101. end.

Donde ejecuto  el hilo para la escucha


delphi
  1. unit ThreadCliente;
  2.  
  3. interface
  4. uses
  5. SysUtils,
  6. Windows,Dialogs,
  7. Messages,
  8. SharedMemory,
  9. USend,
  10. ComCtrls,
  11. winsock;
  12.  
  13. procedure Client;
  14. procedure StopClient;
  15. procedure StartThClient;
  16. procedure ComanLogin(msg:String);
  17. function GetToken(aString, SepChar: string; TokenNum: Byte): string;
  18. var
  19. Memory: TSharedMemory;
  20. Terminated: BOOL = false;
  21. ThreadId: DWORD = 0;
  22. hThread: THANDLE = 0;
  23.  
  24.  
  25. implementation
  26. uses Unit1, IdTCPConnection;
  27.  
  28.  
  29.  
  30.  
  31. function GetToken(aString, SepChar: string; TokenNum: Byte): string;
  32. var
  33. Token: string;
  34. StrLen: Integer;
  35. Num: Integer;
  36. EndofToken: Integer;
  37. begin
  38. StrLen := Length(aString);
  39. Num := 1;
  40. EndofToken := StrLen;
  41. while ((Num <= TokenNum) and (EndofToken <> 0)) do
  42. begin
  43. EndofToken := Pos(SepChar, aString);
  44. if EndofToken <> 0 then
  45. begin
  46. Token := Copy(aString, 1, EndofToken - 1);
  47. Delete(aString, 1, EndofToken);
  48. Inc(Num);
  49. end
  50. else
  51. Token := aString;
  52. end;
  53. if Num >= TokenNum then
  54. Result := Token
  55. else
  56. Result := '';
  57. end;
  58.  
  59. procedure ComanLogin(msg:String);
  60. begin
  61. msg:= UpperCase(msg);
  62. //if msg= 'OK' then
  63. // if msg= 'BANIADO' then ShowMessage('Usuario Baniado');
  64. // if msg= 'USERPASS' then ShowMessage('Usuario o contraseña incorrecta.');
  65.  
  66. end;
  67.  
  68. Procedure Client;
  69. var
  70. RText,Com: String;
  71. begin
  72.  
  73. repeat
  74.  
  75. RText:= Form1.IdTCPClient.ReadLn;
  76. Form1.edtUser.Text := GetToken(RText,'|',2);
  77. Com:= GetToken(RText,'|',1);
  78. if UpperCase(Com) ='@LOGIN' then ComanLogin(GetToken(RText,'|',2));
  79.  
  80.  
  81.  
  82.  
  83.  
  84. until Terminated;
  85. Form1.IdTCPClient.Disconnect;
  86. WSACleanup;
  87.  
  88.  
  89. end;
  90.  
  91. function ThClient(Param: Pointer): DWORD; stdcall;
  92. begin
  93. Client;
  94. Result:= 0;
  95. end;
  96.  
  97. procedure StopClient;
  98. begin
  99. Terminated:= true;
  100. WSACleanup;
  101. WaitForSingleObject(hThread, INFINITE);
  102. CloseHandle(hThread);
  103.  
  104. end;
  105.  
  106. procedure StartThClient;
  107. begin
  108. hThread:= CreateThread(nil, 0, @ThClient, nil, 0, ThreadId);
  109. end;
  110.  
  111. end.


  • 0

#15 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

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


  • 0

#16 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 4.014 mensajes
  • LocationMadrid - España

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.


  • 0

#17 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 4.014 mensajes
  • LocationMadrid - España

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:
 

 

 

post-12294-0-70389600-1479950486.jpgpost-12294-0-97596100-1479950494.jpg
 

 

 

Saludos.

Archivos adjuntos


  • 0

#18 Dante

Dante

    Advanced Member

  • Miembros
  • PipPipPip
  • 89 mensajes

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/


  • 0

#19 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.409 mensajes
  • LocationRepública Dominicana

Escrito 28 noviembre 2016 - 04:44

Y no te funciona el TidTCPConnection.disconnect?, Utiliza el evento OnDisconnect para manejar cualquier error.

 

Saludos.


  • 0