Recent

Author Topic: can i make server?  (Read 69027 times)

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: can i make server?
« Reply #120 on: October 23, 2017, 12:06:02 pm »
In the beginning I told you about proper indentation.
Your code wobbels all over.
Please use proper indentation and you see what you did wrong.

If canread() is false there can still be an error. So checking for an error inside the begin/end if the canread check is useless.

Next you check for "if i < high(connections) then" before you are moving/deleting a connection.
But when i = high(connections) then "for j := i + 1 to high(connections) do" won't be executed anyway.
So you don't even have to check for it because if i = high(connections) the moving won't take place.

You can also simplify the code by eliminating "if length(connections) = 1 then".
You can just do the check for error, move the connection 1 up, and if at the end length(connections) = 0 you can disable the button and edit and add text to the memo. So try to streamline that code a bit.

O, and you didn't use continue inside the loop when you move the connections up. So in the timer in that case one connection is always skipped (until the next timer-event). That might not seem like a big deal because the timer runs frequently but it's best to do it the correct way.
« Last Edit: October 23, 2017, 12:08:01 pm by rvk »

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #121 on: October 23, 2017, 12:22:29 pm »
sorry i don't get this part
Quote
Next you check for "if i < high(connections) then" before you are moving/deleting a connection.
But when i = high(connections) then "for j := i + 1 to high(connections) do" won't be executed anyway.
So you don't even have to check for it because if i = high(connections) the moving won't take place.

You can also simplify the code by eliminating "if length(connections) = 1 then".

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: can i make server?
« Reply #122 on: October 23, 2017, 12:28:03 pm »
sorry i don't get this part
Quote
Next you check for "if i < high(connections) then" before you are moving/deleting a connection.
But when i = high(connections) then "for j := i + 1 to high(connections) do" won't be executed anyway.
So you don't even have to check for it because if i = high(connections) the moving won't take place.

You can also simplify the code by eliminating "if length(connections) = 1 then".

You now have this:
Code: Pascal  [Select][+][-]
  1.           if i < high(connections) then
  2.           begin
  3.             ConnectionS[i].sock.CloseSocket;
  4.             ConnectionS[i].sock.Free;
  5.             for j := i + 1 to high(connections) do
  6.             begin
  7.               connections[j - 1] := connections[j];
  8.             end;
  9.             memo1.Lines.add('*Clinet ' + IntToStr(i + 1) + ' disconnected');
  10.             setlength(connections, length(connections) - 1);
  11.           end;
  12.           if i = high(connections) then
  13.           begin
  14.             setlength(connections, length(connections) - 1);
  15.             ConnectionS[i].sock.CloseSocket;
  16.             ConnectionS[i].sock.Free;
  17.             setlength(connections, length(connections) - 1);
  18.             memo1.Lines.add('*Clinet ' + IntToStr(i + 1) + ' disconnected');
  19.           end;
But "if i < high(connections) then" part can also be executed for "if i = high(connections) then".
This is because if "i = high(connections)" then line 5,6,7,8 (highlighted) wil not be executed.
Because it would read "for high(connections) + 1 to high(connections) do".
And if you have "for 5 to 4 do" nothing is executed because 4 is lower than 5.

So you can just remove the "if i < high(connections) then" line and erase the whole "if i = high(connections) do" block.

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #123 on: October 23, 2017, 12:38:51 pm »
Code: Pascal  [Select][+][-]
  1. So you can just remove the "if i < high(connections) then" line and erase the whole "if i = high(connections) do" block.
but if i remove this, won't i get the error message if i close the last client program?
for example, let's say i opened 3 client programs where high(connections) is 2 and the 3rd client program's "i" is 2.
but for this code
Code: Pascal  [Select][+][-]
  1. for j := i + 1 to high(connections) do
  2.             begin
  3.               connections[j - 1] := connections[j];
  4.             end;
it will be "j:= (2)+1 to (2) do"
so it will be"3 to 2 do" which won't work right?

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: can i make server?
« Reply #124 on: October 23, 2017, 12:45:01 pm »
it will be "j:= (2)+1 to (2) do"
so it will be"3 to 2 do" which won't work right?
The fun fact is that this WILL work. It just does nothing.
If in the FOR statement the beginning is higher than the end, the FOR statement is just skipped. There is no error message whatsoever. So it's perfectly fine to do this.

(Your error was due to something else, so first follow all three suggestions I gave).

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #125 on: October 23, 2017, 01:00:29 pm »
Code: Pascal  [Select][+][-]
  1.  
  2.   I := 0;
  3.   while I <= High(connections) do
  4.   begin
  5.   Application.ProcessMessages;
  6.  
  7.      if ConnectionS[i].sock.canread(100) then
  8.       begin
  9.         S := ConnectionS[i].sock.RecvString(120000);
  10.         memo1.lines.add('client '+inttostr(i+1)+ ' : ' +S);
  11.         for j:= 0 to high(connections) do
  12.         begin
  13.           if j <> i then
  14.            begin
  15.              connections[j].sock.SendString('client '+inttostr(i+1)+ ' : ' +s + crlf);
  16.            end;
  17.         end;
  18.       end;
  19.  
  20.      if (connections[i].sock.lasterror <> 0)  then
  21.         begin
  22.           ConnectionS[i].sock.CloseSocket;
  23.           ConnectionS[i].sock.Free;
  24.           for j:= i+1 to high(connections) do
  25.             begin
  26.                 connections[j-1]:=connections[j]
  27.             end;
  28.           memo1.lines.add('*Clinet ' + inttostr(i+1) + ' disconnected');
  29.           setlength(connections, length(connections) -1);
  30.           continue;
  31.           end;
  32.  
  33.  
  34.      Inc(I);
  35.   end;
  36.  
  37.      if length(connections) = 0 then
  38.       begin
  39.        edit3.clear;
  40.         edit3.enabled:=false;
  41.         button2.enabled:=false;
  42.         timer1.enabled:=false;
  43.  
  44.         ConnectionS[i].sock.CloseSocket;
  45.         ConnectionS[i].sock.Free;
  46.  
  47.         setlength(connections, 0);
  48.  
  49.         memo1.lines.add('Clinet ' + inttostr(i+1) + 'disconnected');
  50.          memo1.lines.add( '------------------------------------------------------------------------');
  51.         memo1.lines.add('Connection closed');
  52.         memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  53.         memo1.lines.add('Waiting for new connection');
  54.         exit; // <- we can exit because we closed the connection
  55.       end;
  56.                  
is it correct?

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: can i make server?
« Reply #126 on: October 23, 2017, 01:17:46 pm »
is it correct?
I do remember already saying that you don't need to use Application.ProcessMessages in the timer-event.

In the last part of "if length(connections) = 0 then" you have
Code: Pascal  [Select][+][-]
  1. ConnectionS[i].sock.CloseSocket;
  2. ConnectionS[i].sock.Free;
  3. setlength(connections, 0);
Those lines are not needed.
First you don't have I anymore because you're outside the while loop.
And second you already disposed of the socket inside the while loop.
Also SetLength to 0 is not needed because with "if length(connections) = 0" you already know it is 0.
The exit in the end is also not needed because you're already at the end of the timer-event and exit does nothing (because there is no code after it).

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #127 on: October 23, 2017, 01:34:59 pm »
thank you it works very well now
i don't know why but i from client 3, i cannot connect to the server
i connected client 1 and 2 to the server but when i tried to connect client 3 to server, it says it is connected on the client program but it doesn't say anything on the server.
and it can't receive the string nor send it

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: can i make server?
« Reply #128 on: October 23, 2017, 01:39:10 pm »
thank you it works very well now
i don't know why but i from client 3, i cannot connect to the server
i connected client 1 and 2 to the server but when i tried to connect client 3 to server, it says it is connected on the client program but it doesn't say anything on the server.
and it can't receive the string nor send it
Weird that the client says it is connected then.

What is the complete source of client and server now?

Is client 3 inside your own network?

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #129 on: October 23, 2017, 01:52:15 pm »
server
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   ExtCtrls, blcksock;
  10.  
  11. type
  12.   ConnectionType = record
  13.     Sock: TTCPBlockSocket;
  14.     ClientName: String;
  15.   end;
  16.  
  17.   { TForm1 }
  18.  
  19.   TForm1 = class(TForm)
  20.     Button1: TButton;
  21.     Button2: TButton;
  22.     Edit1: TEdit;
  23.     Edit2: TEdit;
  24.     Edit3: TEdit;
  25.     Label1: TLabel;
  26.     Label2: TLabel;
  27.     Label3: TLabel;
  28.     Memo1: TMemo;
  29.     Timer1: TTimer;
  30.     Timer2: TTimer;
  31.     procedure Button1Click(Sender: TObject);
  32.     procedure Button2Click(Sender: TObject);
  33.     procedure Edit3KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  34.     procedure FormCreate(Sender: TObject);
  35.  
  36.     procedure Timer1Timer(Sender: TObject);
  37.     procedure Timer2Timer(Sender: TObject);
  38.   private
  39.     { private declarations }
  40.   public
  41.     { public declarations }
  42.   end;
  43.  
  44. var
  45.   Connections: array of ConnectionType;
  46.   Form1: TForm1;
  47.   ListenerSocket: TTCPBlockSocket;
  48.  
  49.   sock: TTCPBlockSocket;
  50.  
  51. implementation
  52.  
  53. {$R *.lfm}
  54.  
  55. { TForm1 }
  56.  
  57. procedure TForm1.FormCreate(Sender: TObject);
  58. begin
  59.   edit1.clear;
  60.   edit2.clear;
  61.   edit3.clear;
  62.   memo1.lines.Clear;
  63. end;
  64.  
  65. procedure TForm1.Button1Click(Sender: TObject);
  66. var
  67.   date:integer;
  68. begin
  69.   //time:=FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now);
  70.   ListenerSocket := TTCPBlockSocket.Create;
  71.  
  72.  
  73.   ListenerSocket.CreateSocket;
  74.   ListenerSocket.setLinger(true,10);
  75.   ListenerSocket.bind(edit1.text ,edit2.text);
  76.   ListenerSocket.listen;
  77.   memo1.lines.add('waiting...');
  78.  
  79.  
  80.   repeat
  81.     Application.ProcessMessages;
  82.  
  83.     if ListenerSocket.canread(100) then // <--- use 100 here instead of 1000
  84.     begin
  85.       edit3.enabled:=true;
  86.       button2.enabled:=true;
  87.  
  88.       SetLength(Connections, Length(Connections) + 1);
  89.       Connections[high(Connections)].Sock := TTCPBlockSocket.Create;
  90.       Connections[high(Connections)].Sock.Socket := ListenerSocket.Accept;
  91.       Timer1.enabled:=true;
  92.       //memo1.lines.add('');
  93.       //memo1.lines.add('Incoming connection');
  94.       memo1.lines.add('Client '+inttostr(length(connections)) + ' is connected');
  95.       //if (Connections[high(connections)].sock.canread(100)) and (Connections[high(connections)].sock.lasterror = 0)then
  96.        Timer1.enabled:=true;
  97.  
  98.       //memo1.lines.add('Client connected on local port: '+ ', '+inttostr(ConnectionSocket.LocalSin.sin_port)+ ', '+ inttostr(ConnectionSocket.RemoteSin.sin_port));
  99.       if length(connections) = 1 then
  100.         begin
  101.         memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  102.         memo1.lines.add( '------------------------------------------------------------------------');
  103.         memo1.lines.add( 'Say Something');
  104.         end;
  105.  
  106.     end;
  107.  
  108.   until false;
  109.  
  110.   //ListenerSocket.Free;
  111.   //memo1.lines.add('done');
  112.  
  113. end;
  114.  
  115. procedure TForm1.Button2Click(Sender: TObject);
  116. var
  117.   buffer:string;
  118.   i: Integer;
  119. begin
  120.   for i := 0 to high(connections) do
  121.   begin
  122.     buffer := edit3.text;//'hello, this is a client';
  123.     connections[i].sock.SendString(buffer + CRLF);
  124.   end;
  125.   memo1.lines.add('Me : '+buffer);
  126.  
  127. end;
  128.  
  129.  
  130. procedure TForm1.Edit3KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
  131.   );
  132.  
  133. begin
  134.   if Key = 13 { or VK_RETURN  and add lcltype in your uses }  then
  135.   begin
  136.     button2.click;
  137.   end;
  138. end;
  139.  
  140. procedure TForm1.Timer1Timer(Sender: TObject);
  141. var
  142.   s:string;
  143.   i, j: Integer;
  144. begin
  145.  
  146.  
  147.  
  148.   I := 0;
  149.   while I <= High(connections) do
  150.   begin
  151.  
  152.      if ConnectionS[i].sock.canread(100) then
  153.       begin
  154.         S := ConnectionS[i].sock.RecvString(120000);
  155.         memo1.lines.add('client '+inttostr(i+1)+ ' : ' +S);
  156.         for j:= 0 to high(connections) do
  157.         begin
  158.           if j <> i then
  159.            begin
  160.              connections[j].sock.SendString('client '+inttostr(i+1)+ ' : ' +s + crlf);
  161.            end;
  162.         end;
  163.       end;
  164.  
  165.      if (connections[i].sock.lasterror <> 0)  then
  166.         begin
  167.           ConnectionS[i].sock.CloseSocket;
  168.           ConnectionS[i].sock.Free;
  169.           for j:= i+1 to high(connections) do
  170.             begin
  171.                 connections[j-1]:=connections[j]
  172.             end;
  173.           memo1.lines.add('*Clinet ' + inttostr(i+1) + ' disconnected');
  174.           setlength(connections, length(connections) -1);
  175.           continue;
  176.           end;
  177.  
  178.  
  179.      Inc(I);
  180.   end;
  181.  
  182.      if length(connections) = 0 then
  183.       begin
  184.        edit3.clear;
  185.         edit3.enabled:=false;
  186.         button2.enabled:=false;
  187.         timer1.enabled:=false;
  188.  
  189.  
  190.  
  191.         memo1.lines.add('Clinet ' + inttostr(i+1) + 'disconnected');
  192.          memo1.lines.add( '------------------------------------------------------------------------');
  193.         memo1.lines.add('Connection closed');
  194.         memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  195.         memo1.lines.add('Waiting for new connection');
  196.         //exit; // <- we can exit because we closed the connection
  197.       end;
  198.  
  199. end;                              

client
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  9.   ExtCtrls, blcksock;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     Button1: TButton;
  17.     Button2: TButton;
  18.     Edit1: TEdit;
  19.     Edit2: TEdit;
  20.     Edit3: TEdit;
  21.     Label1: TLabel;
  22.     Label2: TLabel;
  23.     Label3: TLabel;
  24.     Memo1: TMemo;
  25.     Timer1: TTimer;
  26.     procedure Button1Click(Sender: TObject);
  27.     procedure Button2Click(Sender: TObject);
  28.     procedure Edit3KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  29.     procedure FormCreate(Sender: TObject);
  30.     procedure Timer1Timer(Sender: TObject);
  31.   private
  32.     { private declarations }
  33.   public
  34.     { public declarations }
  35.   end;
  36.  
  37. var
  38.   Form1: TForm1;
  39.   sock: TTCPBlockSocket;
  40.   buffer: string;
  41.  
  42. implementation
  43.  
  44. {$R *.lfm}
  45.  
  46. { TForm1 }
  47.  
  48. procedure TForm1.FormCreate(Sender: TObject);
  49. begin
  50.   edit1.clear;
  51.   edit2.clear;
  52.   edit3.clear;
  53.   memo1.lines.clear;
  54. end;
  55.  
  56. procedure TForm1.Timer1Timer(Sender: TObject);
  57. var
  58.   s:string;
  59. begin
  60.  
  61.    if Sock.canread(100) then
  62.       begin
  63.         S := sock.RecvString(120000);
  64.         memo1.lines.add('server : '+S);
  65.       end;
  66.  
  67.   if sock.lasterror <> 0 then
  68.   begin
  69.     edit3.clear;
  70.     timer1.Enabled:=false;
  71.     edit3.enabled:=false;
  72.     button2.enabled:=false;
  73.     memo1.lines.add( '------------------------------------------------------------------------');
  74.      memo1.lines.add('Connection closed');
  75.      memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  76.      memo1.lines.add('Waiting for new connection');
  77.   end;
  78. end;
  79.  
  80. procedure TForm1.Button1Click(Sender: TObject);
  81. var
  82. s : string;
  83. begin
  84.   sock := TTCPBlockSocket.Create;
  85.   sock.Connect(edit1.text, edit2.text);
  86.  
  87.  
  88.    if sock.LastError <> 0 then
  89.   begin
  90.     memo1.lines.add('Could not connect to server.');
  91.     //halt(1);
  92.   end;
  93.  
  94.    if sock.LastError = 0 then
  95.   begin
  96.     memo1.lines.add('Connected to the server');
  97.     memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  98.     memo1.lines.add( '------------------------------------------------------------------------');
  99.     memo1.lines.add('Say Something');
  100.     edit3.enabled:=true;
  101.     button2.enabled:=true;
  102.     timer1.enabled:=true;
  103.     //halt(1);
  104.   end;
  105. end;
  106.  
  107. procedure TForm1.Button2Click(Sender: TObject);
  108. var
  109.   s:string;
  110. begin
  111.     buffer := edit3.text;//'hello, this is a client';
  112.     sock.SendString(buffer + CRLF);
  113.     memo1.lines.add('Me : '+buffer);
  114. end;
  115.  
  116. procedure TForm1.Edit3KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  117. begin
  118.  if Key = 13 { or VK_RETURN  and add lcltype in your uses }  then   button2.click;
  119. end;
  120.  
  121.  
  122. end.
  123.                          
Quote
Is client 3 inside your own network?
yes

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: can i make server?
« Reply #130 on: October 23, 2017, 02:10:21 pm »
And if you try it on the same computer.
I have no trouble to create 4 clients on the same computer.
On different computers it should work too.
If one computer doesn't work as client 3, does that computer work as client 2 ??

piGrimm

  • Guest
Re: can i make server?
« Reply #131 on: October 23, 2017, 02:14:37 pm »
if it doesnt work smart for 2-3 clients, whant about 3000 ? 30000... >:D OMG

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: can i make server?
« Reply #132 on: October 23, 2017, 02:27:19 pm »
if it doesnt work smart for 2-3 clients, whant about 3000 ? 30000... >:D OMG
It does work for client 1 and client 2 so it should work for client 3 too.
That number should easily go up to 200 or 300.
Above that resources might become a problem.

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #133 on: October 23, 2017, 02:30:31 pm »
mine is not working

rvk

  • Hero Member
  • *****
  • Posts: 6171
Re: can i make server?
« Reply #134 on: October 23, 2017, 02:40:25 pm »
mine is not working
You said client 3 didn't connect but according to your picture, client 2 doesn't connect either...
(at least I don't see the connect of client 2 on the server)

I thought it might be because you did a bind to 127.0.0.1 on the server (instead of 0.0.0.0) but I tried it here and if all use 127.0.0.1 it should work too.

Do you have a firewall?
What OS-version are you using.

 

TinyPortal © 2005-2018