[SOLVED] Synapse what's wrong? lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- Jake012345 · 2020-05-14 09:43 Hello! I did this code and it's can connect, but can't send messages to each other. why? server: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,  laz_synapse, blcksock; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Edit1: TEdit;    Edit2: TEdit;    Memo1: TMemo;    Timer1: TTimer;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);    procedure FormCreate(Sender: TObject);    procedure Timer1Timer(Sender: TObject);  private   public   end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 }  var listenersocket:TBlockSocket;     connection:TBlockSocket;     socknum:integer;     connected:boolean;     commessage:string; procedure TForm1.Button1Click(Sender: TObject); var sz:integer;begin  //HOST   listenersocket:=TBlockSocket.Create;  listenersocket.CreateSocket;  if Edit1.Text='' then Edit1.Text:='11';  listenersocket.Bind('192.168.0.101',Edit1.Text);  listenersocket.Listen;   repeat      Application.ProcessMessages;    if listenersocket.CanRead(10) then begin        connection:=TBlockSocket.Create;        connection.Socket:=listenersocket.Accept;        connected:=true;      memo1.Append('connection setted up!');      end;  until false; end; procedure TForm1.Button2Click(Sender: TObject); var sz:integer;     message:string;begin  if connected=true then begin    message:=Edit2.Text;    connection.SendString(message);   end;end; procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);begin  halt;end; procedure TForm1.FormCreate(Sender: TObject);begin  socknum:=1;end; procedure TForm1.Timer1Timer(Sender: TObject);  var sz:integer;begin   Application.ProcessMessages;  if connected=true then begin      commessage:=connection.RecvString(10);      if commessage<>'' then Memo1.Lines.Append(commessage);    end;end; end.   client: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,  laz_synapse, blcksock; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    Edit1: TEdit;    Edit2: TEdit;    Edit3: TEdit;    Memo1: TMemo;    Timer1: TTimer;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure FormCreate(Sender: TObject);    procedure Timer1Timer(Sender: TObject);  private   public   end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } var connection:TBlockSocket;    connected:boolean;    messagein:string; procedure TForm1.FormCreate(Sender: TObject);beginend; procedure TForm1.Timer1Timer(Sender: TObject);begin  Application.ProcessMessages;  if connected=true then begin    messagein:=connection.RecvString(10);    if not(messagein='') then begin      Memo1.Append(messagein);    end;  end;end; procedure TForm1.Button1Click(Sender: TObject);  var sz:integer;      sz2:integer;begin  //Connect  if Edit1.Text='' then Edit1.Text:='192.168.0.101';  if Edit2.Text='' then Edit2.Text:='11';   connection:=TBlockSocket.Create;  connection.CreateSocket;  connection.Connect(Edit1.Text,Edit2.Text);   if connection.LastError=0 then begin    connected:=true;    Memo1.Lines.Append('Connected!');  end; end; procedure TForm1.Button2Click(Sender: TObject);  var message:string;begin  if connected=true then begin    message:=Edit3.Text;    connection.SendString(message);  end;end; end.   Thanks for solution! ---------------------------------------------------------------------- rvk · 2020-05-14 10:09 The problem is that you don't work with threads. In Button1Click in the server you have a repeat until false. You never leave that event. Therefore the timer-event will never trigger. TTimer events are executed in the main thread but if you have a 'hanging' event procedure it will never come to that. So make sure the Button1Click event ends before you can read from the connection. Or better, use threads. ---------------------------------------------------------------------- Jake012345 · 2020-05-14 10:37 But how can I test it? Or make threads? ---------------------------------------------------------------------- rvk · 2020-05-14 12:34 Quote from: Jake012345 on May 14, 2020, 12:37:07 pmBut how can I test it? Or make threads? To test it you could do an break inside the repeat until loop. Below the memo1.Append('connection setted up!'); In that case, when the first connection is setup, the program will run on and your timer will function. But it will only work once for the first connection you do. When you end the connection and click the server button again, you'll get errors because there is already a listening socket (which you can't use anymore because you exited the function before). If you really don't want to work with threads you need to setup the listening socket in formcreate (or in a special StartServer function) which you only execute once. Then the listening loop can be run (with another button or automatically). When the connection is terminated you can again run the loop function to listen for another connection. But it would be better to move everything to a thread. In that case you can spawn multiple connections and receive messages from multiple clients. In the standard .zip download of version 40 you'll find an example. synapse40\source\demo\echo\echo.pas (Although it's best you work with the trunk version at https://sourceforge.net/p/synalist/code/HEAD/tree/trunk/ (use the download button right above) the examples are only to be found in the synapse40.zip) ---------------------------------------------------------------------- lucamar · 2020-05-14 13:53 Quote from: rvk on May 14, 2020, 12:09:01 pmIn Button1Click in the server you have a repeat until false. You never leave that event. Therefore the timer-event will never trigger. That's not quite true, is it? Note that he calls ProcessMessages in the very first line of the loop so the timer messages should be getting through on each iteration. Though I'll agree with you that in this case he would be better off using threads ---------------------------------------------------------------------- Jake012345 · 2020-05-14 13:54 Can You share an example? I can't do it not at all... ---------------------------------------------------------------------- rvk · 2020-05-14 15:10 Quote from: lucamar on May 14, 2020, 03:53:01 pmQuote from: rvk on May 14, 2020, 12:09:01 pmIn Button1Click in the server you have a repeat until false. You never leave that event. Therefore the timer-event will never trigger.That's not quite true, is it? Note that he calls ProcessMessages in the very first line of the loop so the timer messages should be getting through on each iteration. Yes, You are correct about the ProcessMessages. Quote from: Jake012345 on May 14, 2020, 03:54:16 pmCan You share an example? I can't do it not at all... I don't have time now to create a complete example but the echo.pas I mentioned has a thread example. For your current code... you shouldn't use such low port number like 11. Use something high like 20011. (I'm not sure why your example doesn't run, because like lucamar mentioned, it should work because of the processmessages) ---------------------------------------------------------------------- Jake012345 · 2020-05-15 10:48 Okay, I got something!! If the connection done, the server can see it, but the client no. (?!!?) But if I send something to client and the client has a procedure, for example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i If connection.CanRead(100) then  Memo1.Append('Got it!');  the client show the 'Got it!' message. Every time when I send something from server. But I can't read the messages yet.. ---------------------------------------------------------------------- rvk · 2020-05-15 10:54 Aaaaargh. You are correct. Look at http://synapse.ararat.cz/doc/help/blcksock.TBlockSocket.html#S endString When using sendstring the crlf is not send with it. Although the recvstring does wait until it receives a crlf termination. So, add the CR-LF in every sendstring and it schould work. Note: the canread does see there is data but the recvstring waits until it has the linetermination. ---------------------------------------------------------------------- Jake012345 · 2020-05-15 12:49 I can't understand it... I added CR+LF to programs Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i messageout:=(Edit2.Text);cinnection.SendString(messageout+CR+LF);  But the server can read the incoming messages after sending (so if I sent something to server, I can't see until I press the send button and send something) If I used the wrong timeouts, (timer.interval=50, but the timeouts=1000) the client could receive the messages and show it until freezing... But I repaired the timeouts (timer.interval=1000, timeouts=10) And the procedure what I wrote in timer too, Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   Application.ProcessMessages;    if connected=true then    if connection.CanRead(10) then begin       Application.ProcessMessages;    messagein:=connection.RecvString(10);      if not(messagein='') then begin        Memo1.Append(messagein);      end;    end; if k=0 then                                              //<-- if connected=true then                                 //<--  if connection.LastError=0 then begin                 //<--    Memo1.Lines.Append('Connected!');                 //<--   This    s:=connection.GetRemoteSinIP;                    //<--    memo1.Append(s);                                //<--    k:=1;                                        //<--  end;                                          //<--  Always run,  BUT just when I move the window. (??!!) Why don't like me the synapse? ---------------------------------------------------------------------- rvk · 2020-05-15 14:54 Quote from: Jake012345 on May 15, 2020, 02:49:24 pmI can't understand it... I added CR+LF to programs I'm not sure what goes wrong at your end. I have the timer in both programs set to 10 (although it could slightly be higher). I have the exact same code from your opening post. Added  + #13#10 to the SendString() in both programs and ran them. I can type and receive with both programs without delay and freeze. Try to revert to your code from the opening post. After that you can add new things. It is indeed best to check if there is data in TTimer before firing RcvString() but try it without first (like in your opening post). B.T.W. You can use 0.0.0.0 as ip adres on the server for binding (listening on all network interfaces). The client should indeed use the ip from the server. I still think port 11 should be avoided but it does work (better to use a random port > 1024) 11 is used by other services. https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers So choose one above 1024 which isn't already listed as reserved in the link above. ---------------------------------------------------------------------- Jake012345 · 2020-05-15 15:27 WORKING!!!!!!!!!! Thanks my god! Thanks @rvk! And @lucamar, for useful info.