Recent

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

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #75 on: October 21, 2017, 02:53:35 pm »
oh yeh true sorry i don't know why i put that maybe i just tried copy the code from server :D

so what should i do to allow more clients to connect the server? should i make another client program?

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: can i make server?
« Reply #76 on: October 21, 2017, 02:59:13 pm »
so what should i do to allow more clients to connect the server? should i make another client program?
No, you only need one client program.
So in the client you don't need to change anything.
You can just run the client.exe multiple times on multiple computers or even on the same computer.

You need to change the server because all the clients need to connect to the server.
Does your current server (and client) work with the TTimer now?

Then you need to rename the Connect button to "Accept incoming clients" or something.
You need to disable the button at the top of the buttonclick so you don't accidentally click the button again.

Next you need to create an array for ConnectionSockets (now you have one ConnectionSocket which you check in the TTimer but you need an array of multiple sockets so you can accept multiple incoming connections). Name that one Connections: array of TTCPBlockSocket.

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #77 on: October 21, 2017, 03:06:51 pm »
oh okay the client work with the TTimer but server doesn't the memo adds the line every 100 ms(timer interval)

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2.  
  3. begin
  4.   //time:=FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now);
  5.   ListenerSocket := TTCPBlockSocket.Create;
  6.   ConnectionSocket := TTCPBlockSocket.Create;
  7.   ListenerSocket.CreateSocket;
  8.   ListenerSocket.setLinger(true,10);
  9.   ListenerSocket.bind(edit1.text ,edit2.text);
  10.   ListenerSocket.listen;
  11.   memo1.lines.add('waiting...');
  12.  
  13.  
  14.   if ListenerSocket.lasterror = 0 then timer1.enabled:=true;
  15.  
  16.  
  17.   ListenerSocket.Free;
  18.   memo1.lines.add('done');
  19.  
  20. end;                  

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. begin
  3.       edit3.enabled:=true;
  4.       memo1.lines.add('');
  5.       memo1.lines.add('Incoming connection');
  6.       ConnectionSocket := TTCPBlockSocket.Create; // multiple new ones
  7.       ConnectionSocket.Socket := ListenerSocket.accept;
  8.       memo1.lines.add('Client connected on local port: '+ ', '+inttostr(ConnectionSocket.LocalSin.sin_port)+ ', '+ inttostr(ConnectionSocket.RemoteSin.sin_port));
  9.       memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  10.       HandleConnection(ConnectionSocket);
  11.       ConnectionSocket.CloseSocket;
  12.       ConnectionSocket.Free;
  13.       memo1.lines.add('...');
  14.       memo1.lines.add('Connection closed');
  15.        memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  16.       memo1.lines.add('Waiting for new connection');
  17. end;  

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: can i make server?
« Reply #78 on: October 21, 2017, 03:18:22 pm »
Nope, nope. In the TTimer you shouldn't create the connection. You create the connection earlier (in this case still in the buttonclick).

So the timer only needs this:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   s:string;
  4. begin
  5.   if ConnectionSocket.canread(100) then
  6.   begin
  7.     S := ConnectionSocket.RecvString(120000);
  8.     memo1.lines.add('server : '+S);
  9.   end;
  10. end;    
That's almost exactly the same code as you have in the client because listening to each other is the same way.

Now for the buttonclick... leave all the same except for the procedure handleConnection you set enabled of the timer to true and you uncomment the disconnect of SocketConnection because otherwise you loose the connection. The ConnectionSocket.CloseSocket; and rest of the code you need to put in a FormDestroy (for now because later on we are going to move them)

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #79 on: October 21, 2017, 03:39:38 pm »
Code: Pascal  [Select][+][-]
  1.  if ListenerSocket.lasterror = 0 then timer1.enabled:=true;
  2.  
  3.     if ListenerSocket.canread(100) then // <--- use 100 here instead of 1000
  4.     begin
  5.       edit3.enabled:=true;
  6.       memo1.lines.add('');
  7.       memo1.lines.add('Incoming connection');
  8.       ConnectionSocket := TTCPBlockSocket.Create; // multiple new ones
  9.       ConnectionSocket.Socket := ListenerSocket.accept;
  10.       memo1.lines.add('Client connected on local port: '+ ', '+inttostr(ConnectionSocket.LocalSin.sin_port)+ ', '+ inttostr(ConnectionSocket.RemoteSin.sin_port));
  11.       memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  12.       ConnectionSocket.CloseSocket;
  13.       ConnectionSocket.Free;
  14.       memo1.lines.add('...');
  15.       memo1.lines.add('Connection closed');
  16.        memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  17.       memo1.lines.add('Waiting for new connection');
  18.     end;  

so do i put like this? i need to take out the loop right?
Quote
uncomment the disconnect of SocketConnection
which one is that?

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: can i make server?
« Reply #80 on: October 21, 2017, 03:45:46 pm »
You should enable the timer AFTER the assignment of ConnectionSocket.Socket with the newly created socket of ListeningConnection.Accept.

And everything onward from ConnectionSocket.CloseSocket; should go to the destroy (or after a loop but that's for later).

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #81 on: October 21, 2017, 04:00:27 pm »
so you still want me to put loop in the OnButton1Click?

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: can i make server?
« Reply #82 on: October 21, 2017, 04:10:29 pm »
so you still want me to put loop in the OnButton1Click?
Not yet.
We are going to do that later on when you are designing multiple incoming connections.
In that loop you would check for incoming additional connections/clients.
I know I said a long running event is bad but that's why you need to disable the button at the top of that event.

And for multiple incoming connections/clients you also need to rethink your design.
Because you have a TEdit in the server with which you send a string to the client, but what do you want to do if you have 5 clients? Do they all need to receive the same string? Or do you want to select a client before sendint a string and only send it to that client?

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #83 on: October 21, 2017, 04:21:51 pm »
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   date:integer;
  4. begin
  5.   //time:=FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now);
  6.   ListenerSocket := TTCPBlockSocket.Create;
  7.   ConnectionSocket := TTCPBlockSocket.Create;
  8.   if ListenerSocket.canread(100) then timer1.enabled:=true;
  9.   ListenerSocket.CreateSocket;
  10.   ListenerSocket.setLinger(true,10);
  11.   ListenerSocket.bind(edit1.text ,edit2.text);
  12.   ListenerSocket.listen;
  13.   memo1.lines.add('waiting...');
  14.  
  15.  
  16.  
  17.     if ListenerSocket.canread(100) then // <--- use 100 here instead of 1000
  18.     begin
  19.       edit3.enabled:=true;
  20.       memo1.lines.add('');
  21.       memo1.lines.add('Incoming connection');
  22.       ConnectionSocket := TTCPBlockSocket.Create; // multiple new ones
  23.       ConnectionSocket.Socket := ListenerSocket.accept;
  24.       memo1.lines.add('Client connected on local port: '+ ', '+inttostr(ConnectionSocket.LocalSin.sin_port)+ ', '+ inttostr(ConnectionSocket.RemoteSin.sin_port));
  25.       memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  26.       ConnectionSocket.CloseSocket;
  27.       ConnectionSocket.Free;
  28.       memo1.lines.add('...');
  29.       memo1.lines.add('Connection closed');
  30.        memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  31.       memo1.lines.add('Waiting for new connection');
  32.     end;
  33.  
  34.  
  35.   ListenerSocket.Free;
  36.   memo1.lines.add('done');
  37.  
  38. end;        

i did this but the client cannot connect to the server

Quote
I know I said a long running event is bad but that's why you need to disable the button at the top of that event.
which button is it? the connect button?

Quote
Do they all need to receive the same string?
at this point yes. i think if i want to send different string to different clients it will be too much for me right now

i just want to make clients to connect my server first. but how do you know which one is client1, client2 and client 3? say if i open 3 client programs, how can i know which one is which?

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: can i make server?
« Reply #84 on: October 21, 2017, 04:37:56 pm »
Code: Pascal  [Select][+][-]
  1.     if ListenerSocket.canread(100) then // <--- use 100 here instead of 1000
  2.     begin
  3. //...
Correction... you do need to loop for that. In the original code this was a repeat until loop. Otherwise the if is false and the whole procedure just ends without checking for connections. So correct that back.

Just don't do the CloseSocket after enabling the timer.
(and your Timer1.enabled:=true; was again too soon, it needed to be AFTER the setting of ConnectionSocket.Socket inside the loop)

Quote
Quote
I know I said a long running event is bad but that's why you need to disable the button at the top of that event.
which button is it? the connect button?
Yes, the connect button on the server isn't really a connect button. It's a "Allow incoming connections" button.
Because it's not the server that's initiating the connection but the client is.

Quote
Quote
Do they all need to receive the same string?
at this point yes. i think if i want to send different string to different clients it will be too much for me right now

i just want to make clients to connect my server first. but how do you know which one is client1, client2 and client 3? say if i open 3 client programs, how can i know which one is which?
You could identify them from their IP address but maybe it's best to listen for the first string and set a client-name to that value. That means that the clients need to connect and send their client-name as first string.

And now that you've put a repeat loop in the button of the server and are sending a client-name from the clients you can also build in the "Connections: array of TTCPBlockSocket" I mentioned earlier.

Remove the variable ConnectionSocket and replace it with the Connection[xxx] variable.
Before the Connection[xxx].Socket := ListeningSocket.Accept you need to enlarge the array and create the TTCPBlockSocket.

And actually, because you want to use client-names you can use this:
Code: Pascal  [Select][+][-]
  1. type
  2.   ConnectionType = record
  3.     Sock: TCPBlockSocket;
  4.     ClientName: String;
  5.   end;
  6.  
  7. var
  8.   Connections: array of ConnectionType;
And on an incoming connection:
Code: Pascal  [Select][+][-]
  1. SetLength(Connections, Length(Connections) + 1);
  2. Connections[Length(Connections)].Sock := TTCPBlockSocket.Create;
  3. Connections[Length(Connections)].Sock.Socket := ListenerSocket.Accept;
  4. Timer1.enabled:=true; // <-- here we can start listening to strings

Then in the timer you need to check if ever Connections record is you CanRead(100) from it.
If you can you read the string from it and you check if clientname is set.
If clientname isn't already set, then set the name in the Connections record
If the clientname was set you can print the message to the memo.

(I hope you understand this a bit :) )
« Last Edit: October 21, 2017, 04:40:05 pm by rvk »

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #85 on: October 21, 2017, 05:17:57 pm »
oh okay yes i understood a bit thank you :)

im still trying to fix my server ttimer1 it's not working
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   date:integer;
  4. begin
  5.   //time:=FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now);
  6.   ListenerSocket := TTCPBlockSocket.Create;
  7.   ConnectionSocket := TTCPBlockSocket.Create;
  8.  
  9.   ListenerSocket.CreateSocket;
  10.   ListenerSocket.setLinger(true,10);
  11.   ListenerSocket.bind(edit1.text ,edit2.text);
  12.   ListenerSocket.listen;
  13.   memo1.lines.add('waiting...');
  14.  
  15.  
  16.   repeat
  17.  
  18.     if ListenerSocket.canread(100) then // <--- use 100 here instead of 1000
  19.     begin
  20.       edit3.enabled:=true;
  21.       memo1.lines.add('');
  22.       memo1.lines.add('Incoming connection');
  23.       ConnectionSocket := TTCPBlockSocket.Create; // multiple new ones
  24.       ConnectionSocket.Socket := ListenerSocket.accept;
  25.      timer1.enabled:=true;
  26.       memo1.lines.add('Client connected on local port: '+ ', '+inttostr(ConnectionSocket.LocalSin.sin_port)+ ', '+ inttostr(ConnectionSocket.RemoteSin.sin_port));
  27.       memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  28.       //ConnectionSocket.CloseSocket;
  29.       //ConnectionSocket.Free;
  30.       //memo1.lines.add('...');
  31.       //memo1.lines.add('Connection closed');
  32.        //memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  33.       //memo1.lines.add('Waiting for new connection');
  34.     end;
  35.     Application.ProcessMessages;
  36.   until false;
  37.  
  38.   ListenerSocket.Free;
  39.   memo1.lines.add('done');
  40.  
  41. end;            

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   s:string;
  4. begin
  5.   Application.ProcessMessages;
  6.   //if ConnectionSocket.canread(100) then
  7.   if connectionsocket.lasterror = 0 then
  8.   begin
  9.  
  10.     S := ConnectionSocket.RecvString(120000);
  11.     memo1.lines.add('server : '+S);
  12.   end
  13.  
  14.   else if connectionsocket.lasterror <> 0 then
  15.   begin
  16.     edit3.enabled:=false;
  17.     timer1.enabled:=false;
  18.    ConnectionSocket.CloseSocket;
  19.       ConnectionSocket.Free;
  20.       memo1.lines.add('...');
  21.       memo1.lines.add('Connection closed');
  22.        memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  23.       memo1.lines.add('Waiting for new connection');
  24.  
  25.   end;
  26. end;          

can you tell me what to fix?

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: can i make server?
« Reply #86 on: October 21, 2017, 05:24:33 pm »
You don't (ever) need ProcessMessages in a timer.
A timer-event always needs to end quickly and because it does not have a loop you can remove that line.

But you DO need the canread().
Because now the timers first real line is ConnectionSocket.RecvString(120000); and that will wait 120 seconds until you get a string.

So:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   s:string;
  4. begin
  5.   if connectionsocket.lasterror <> 0 then
  6.   begin
  7.     edit3.enabled:=false;
  8.     timer1.enabled:=false;
  9.     ConnectionSocket.CloseSocket;
  10.     ConnectionSocket.Free;
  11.     memo1.lines.add('...');
  12.     memo1.lines.add('Connection closed');
  13.     memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  14.     memo1.lines.add('Waiting for new connection');
  15.     exit; // <- we can exit because we closed the connection
  16.   end;
  17.  
  18.   // and this part is again the same as in the client
  19.   if ConnectionSocket.canread(100) then
  20.   begin
  21.     S := ConnectionSocket.RecvString(120000);
  22.     memo1.lines.add('server : '+S);
  23.   end;
  24.  
  25. end;

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #87 on: October 21, 2017, 05:35:15 pm »
Code: Pascal  [Select][+][-]
  1.  // and this part is again the same as in the client
  2.   if ConnectionSocket.canread(100) then
  3.   begin
  4.     S := ConnectionSocket.RecvString(120000);
  5.     memo1.lines.add('server : '+S);
  6.   end;
will it also work if you check it if it's connected by saying connectionsocket.lasterror = 0?

rvk

  • Hero Member
  • *****
  • Posts: 6163
Re: can i make server?
« Reply #88 on: October 21, 2017, 05:37:41 pm »
will it also work if you check it if it's connected by saying connectionsocket.lasterror = 0?
What do you gain by checking if you're connected? What is the client does connect but doesn't send anything. We don't want to call RecvString() without there being anything on the line.

So calling ConnectionSocket.canread(100) we know that there is a string waiting on the line.
Checking for ConnectionSocket.LastError doesn't do that. It only checks if there is still a connection.

O, and lasterror only gets filled when we call canread or something. It doesn't get anything without a call. So just checking lasterror is not good. So we need to move the "if connectionsocket.lasterror <> 0 then" after the "if canread" line.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   s:string;
  4. begin
  5.   // and this part is again the same as in the client
  6.   if ConnectionSocket.canread(100) then
  7.   begin
  8.     S := ConnectionSocket.RecvString(120000);
  9.     memo1.lines.add('server : '+S);
  10.   end;
  11.  
  12.   // check if the previous CanRead had an error
  13.   // if there is an error we assume the connection is lost.
  14.   if connectionsocket.lasterror <> 0 then
  15.   begin
  16.     edit3.enabled:=false;
  17.     timer1.enabled:=false;
  18.     ConnectionSocket.CloseSocket;
  19.     ConnectionSocket.Free;
  20.     memo1.lines.add('...');
  21.     memo1.lines.add('Connection closed');
  22.     memo1.lines.add( FormatDateTime('DDDD, dd MMMM YYYY HH:MM:SS', Now));
  23.     memo1.lines.add('Waiting for new connection');
  24.   end;
  25.  
  26. end;
« Last Edit: October 21, 2017, 05:39:52 pm by rvk »

shs

  • Sr. Member
  • ****
  • Posts: 310
Re: can i make server?
« Reply #89 on: October 22, 2017, 05:45:55 am »
Code: Pascal  [Select][+][-]
  1. And on an incoming connection:
  2. Code: Pascal  [Select]
  3. SetLength(Connections, Length(Connections) + 1);
  4. Connections[Length(Connections)].Sock := TTCPBlockSocket.Create;
  5. Connections[Length(Connections)].Sock.Socket := ListenerSocket.Accept;
  6. Timer1.enabled:=true; // <-- here we can start listening to strings
  7.  
  8. Then in the timer you need to check if ever Connections record is you CanRead(100) from it.
wait how can i check if there are more than 2 incoming connections?

 

TinyPortal © 2005-2018