Lazarus

Programming => Networking and Web Programming => Topic started by: balazsszekely on February 25, 2020, 08:41:12 pm

Title: Synapse TCP/IP client and server
Post by: balazsszekely on February 25, 2020, 08:41:12 pm
Since there are very few examples out there, I would like to share a TCP/IP component based on synapse + a small demo application. I hope you will find it useful.
In order to compile the demo, you need two components:
 - Synapse trunk(http://www.ararat.cz/synapse/doku.php/download or OPM)
 - VirtualTreeView available both in 2.0.6 and Trunk. Since the VTV versions are slightly different, I attach two zip files, one for 2.0.6 and one for trunk.

The component supports:
- connection through proxy server(html, proxy4, proxy5)
- encrypted communication
- compressed streaming
- broadcasting
- resource strings which can be easily convert to other languages

The demo was mainly tested with Lazarus Trunk/FPC 3.0.4.

You can download the latest version from here: https://forum.lazarus.freepascal.org/index.php/topic,48677.msg406918.html#msg406918
Title: Re: Synapse TCP/IP client and server
Post by: MoCityMM on March 09, 2020, 01:21:32 pm
Nice! I like it. Thank you for sharing it, adding to my 'howto' repository.

-Mo
Title: Re: Synapse TCP/IP client and server
Post by: nouzi on March 09, 2020, 02:27:23 pm
very nice
Title: Re: Synapse TCP/IP client and server
Post by: chentung on January 29, 2021, 05:04:08 am
wonderful examples !
Thank You !
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on January 29, 2021, 07:30:47 am
wonderful examples !
Thank You !
You're welcome! I attach a slightly improved versions.
Title: Re: Synapse TCP/IP client and server
Post by: chentung on January 30, 2021, 02:58:31 pm
Thank You !
I love it !
Title: Re: Synapse TCP/IP client and server
Post by: Guser979 on March 14, 2021, 02:53:47 am
Thank you very much. I was not able to port forward on my router. So I used Zerotier and all the machines are able to access mine with their server.
Title: Re: Synapse TCP/IP client and server
Post by: Gustavo 'Gus' Carreno on March 31, 2021, 10:02:45 pm
Hey GetMem,

This looks very nice and quite interesting.
Definitely needs a good look.
Superb job!!

Cheers,
Gus
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on May 15, 2021, 11:32:55 pm
Hello GetMem,

thanks for sharing! I'm studying and trying to understand your code right now, especially the data handling between the threads. Two questions:

1. Multithreading
As I understand you add tasks to the task list e.g. within the main thread, the task list is then polled by the TClientThread of the server application. I don't see any protection there when TList.Add is called in order to add a task (E.g. from TfMain.miBroadcastMessageClick via FTCPServer.SendMessage). The task list is accessed in the Execute method of the client thread and first the count property is checked and then in case it is not zero the list is copied to a local TList. That copy sequence is protected in a critical section, but as the list is thread specific, that critical section seems to protect nothing. Or is it just to guarantee a cache flush?
Additionally I wouldn't expect the access to TList.count to be thread safe, but I'm not sure. Can you say something to that data handling concept?


2. Synapse RecvPacket
You use RecvPacket several times, e.g. in TClientThread.RecvMessage (line 685 of uTCPSockets). I'm not sure about the synapse library, but as far as I understand the TCP-protokoll the incoming data is just a byte stream and not bundled in packets. So when you call RecvPacket how can you be sure that what you receive is the complete data and not only half of a message or several messages combined?

Regards~
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on May 19, 2021, 07:34:40 am
Hello kupferstecher,

First of all, sorry for the late response, I was busy with other things.

1. Multithreading
Quote
As I understand you add tasks to the task list e.g. within the main thread, the task list is then polled by the TClientThread of the server application. I don't see any protection there when TList.Add is called in order to add a task (E.g. from TfMain.miBroadcastMessageClick via FTCPServer.SendMessage). The task list is accessed in the Execute method of the client thread and first the count property is checked and then in case it is not zero the list is copied to a local TList. That copy sequence is protected in a critical section, but as the list is thread specific, that critical section seems to protect nothing. Or is it just to guarantee a cache flush?
Additionally I wouldn't expect the access to TList.count to be thread safe, but I'm not sure. Can you say something to that data handling concept?
The idea behind TTaskList is that in order to broadcast a message, we have to lock, then loop through the server's client list. If we perform the actual broadcasting from inside the loop, the server will become unresponsive. By using a thread safe TTaskList, we offload the bulk of the work to the execute event of each client, this way minimize the amount of time the list needs to be locked.
Each TClientThread has its own task list, more over there is no data sharing between the different worker threads, so everything is thread safe, except when new task are added from the main thread. As you correctly noticed, the AddTask method should also be wrapped inside a critical section. I will fix this issue soon, but instead of my own critical sections, I will switch to a TThreadList, which is thread safe by default. I should have gone with a TThreadList in the first place. Thanks for noticing this bug!


2. Synapse RecvPacket
Quote
You use RecvPacket several times, e.g. in TClientThread.RecvMessage (line 685 of uTCPSockets). I'm not sure about the synapse library, but as far as I understand the TCP-protokoll the incoming data is just a byte stream and not bundled in packets. So when you call RecvPacket how can you be sure that what you receive is the complete data and not only half of a message or several messages combined?
I will quote from Synapse documentations:
Quote
Method reads all data waiting for read. If no data is received within
     TIMEOUT (in milliseconds) period, @link(LastError) is set to WSAETIMEDOUT.
     Methods serves for reading unknown size of data. Because before call this
     function you don't know size of received data, returned data is stored in
     dynamic size binary string. This method is preffered for reading from
     stream sockets (like TCP). It is very goot for receiving datagrams too!
     (UDP protocol)}
After a RecvPacket usually I check for errors(FBlockSocket.LastError > 0), so if something went wrong I will know it.
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on May 19, 2021, 12:11:35 pm
Hello GetMem,

thanks for the response!

1. Multithreading
 OK, it's clear now :-)


2. Synapse RecvPacket
For that I'm still not convinced. The docu I also read, and it doesn't say anything about packets, just the available data of the byte stream.

What I mean is, if you send two messages from the client, and after both arrived then you call RecvPacket (and not earlier), then I would expect the function to return the data holding both messages as one string. And I don't see that case handled in your code. The other issue I see is if one message doesn't come as one IP-packet but is split up. If the second one is delayed and RecvPacket is called before arrival, then I expect to get returned the already received data of the first IP-packet. Which is not the complete message. In both cases the FBlockSocket.LastError should be OK / zero.

The reason I looked so close into that is that I think the above issues exist and I'm not sure how to handle them efficiently. Combining partial "packets" always includes some buffering and copying. But perhaps for messages smaller than IP-packet size this is no issue?


When I made some tests and sent a "frame" combined of a byte, a word, a data block and again a byte I checked the network traffic with wireshark. Each part was sent on its own (with fClientSocket.SendBuffer) and according to Wireshark also transfered in its own IP-packet. I would have expected that at least beginning with the second portion, the code should be faster than the network and thus the data should then be transfered combined in one IP-packet. But it wasn't. Could be due to the small data sizes or implementation dependent or I just don't understand the TCP protocol correctly.
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on May 19, 2021, 01:39:39 pm
Quote
2. Synapse RecvPacket
For that I'm still not convinced. The docu I also read, and it doesn't say anything about packets, just the available data of the byte stream.

What I mean is, if you send two messages from the client, and after both arrived then you call RecvPacket (and not earlier), then I would expect the function to return the data holding both messages as one string. And I don't see that case handled in your code. The other issue I see is if one message doesn't come as one IP-packet but is split up. If the second one is delayed and RecvPacket is called before arrival, then I expect to get returned the already received data of the first IP-packet. Which is not the complete message. In both cases the FBlockSocket.LastError should be OK / zero.

The reason I looked so close into that is that I think the above issues exist and I'm not sure how to handle them efficiently. Combining partial "packets" always includes some buffering and copying. But perhaps for messages smaller than IP-packet size this is no issue?


When I made some tests and sent a "frame" combined of a byte, a word, a data block and again a byte I checked the network traffic with wireshark. Each part was sent on its own (with fClientSocket.SendBuffer) and according to Wireshark also transfered in its own IP-packet. I would have expected that at least beginning with the second portion, the code should be faster than the network and thus the data should then be transfered combined in one IP-packet. But it wasn't. Could be due to the small data sizes or implementation dependent or I just don't understand the TCP protocol correctly.
OK. Now I see what you meant. I will look into the issue, but please note I'm not a networking expert either,  I'm not familiar with all the intricacies of TCP/IP protocol. With that said, I do have a closed source project, with a similar structure as the attached demo from my previous post, which is running for years. Multiple clients communicates via the server, exchanging large amount of data, nobody ever complained about data loss.
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on May 19, 2021, 03:56:30 pm
OK, I see. If it works it works :-)

Perhaps some networking experts around here can clarify if its safe that way.
Title: Re: Synapse TCP/IP client and server
Post by: avra on May 20, 2021, 08:10:26 am
OK, I see. If it works it works :-)

Perhaps some networking experts around here can clarify if its safe that way.
I am not a networking expert but I have a dozen of Synapse based tcp/ip and serial applications working 24/7 in heavy industrial environments without leaks or dropped messages. Some of them are made more then 10 years ago (with Delphi 7 and 2006) and there was no reason for any changes since commissioning deployment on Windows servers, and some of them run on Linux servers or ARM boards that do not even restart for more then a year or two and have a high traffic load.

I can say that Synapse works well.  ;)
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on May 20, 2021, 01:10:54 pm
Hello avra,

there's no doubt that Synapse is working very well. The question was if it can be relied on that a buffer/packet sent via TCP ist received as such packet using Synapse's RecvPacket. In my understanding TCP doesn't guarantee that, but only a stream of bytes in the correct order. Just like a Serial port.

Would be interesting to know, how you dealt with this issue, parsing the data stream or relying on packets?

Regards~
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on May 20, 2021, 01:45:58 pm
@kupferstecher
Quote
there's no doubt that Synapse is working very well. The question was if it can be relied on that a buffer/packet sent via TCP ist received as such packet using Synapse's RecvPacket. In my understanding TCP doesn't guarantee that, but only a stream of bytes in the correct order. Just like a Serial port.
Then perhaps you should switch from RecvPacket to another RecvXY(RecvByte, RecvInteger, etc...). In the end all of them rely on RecvBuffer and the low level Recv function.
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on May 20, 2021, 05:46:01 pm
Yes, or using RecvPacket and working with an extra buffer.
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on May 25, 2021, 12:11:48 pm
@kupferstecher

I fixed the issue with the AddTask method, now everything should be thread safe(see attached projects). If you find a way to improve RecvPacket please let me know, so I can integrate it in the test application. Thank you!
Title: Re: Synapse TCP/IP client and server
Post by: Gustavo 'Gus' Carreno on May 26, 2021, 12:55:04 am
Hey GetMem,

Do you have this project in a VCS of ANY sort?

I'm not complaining that you give us the source like you're doing now, it's just that you don't give us the source with a different filename, like v1 and v2, well, you get my meaning.

I'm really interested in this code since I'm planing a server of my own and I'm loving that you are reading comments and improving the code, I do, but could we benefit with an historical record?

Many thanks for the code, in whatever form you give to us, though :)

Cheers,
Gus
Title: Re: Synapse TCP/IP client and server
Post by: irawan on May 26, 2021, 07:58:08 am
Hello avra,

there's no doubt that Synapse is working very well. The question was if it can be relied on that a buffer/packet sent via TCP ist received as such packet using Synapse's RecvPacket. In my understanding TCP doesn't guarantee that, but only a stream of bytes in the correct order. Just like a Serial port.

Would be interesting to know, how you dealt with this issue, parsing the data stream or relying on packets?

Regards~
as far as i know, UDP that is not guarantee that every packet is sent and received correctly. TCP/IP DOES guarantee that every packet is sent correctly altough packet sequence is not guaranteed. coz of this feature, many router will cut your packet if you exceded your quota. in case your packet is dropped by the router, your server will send your dropped packets again and again till download completed. on other side, UDP can not be limited, it's only option is dropped only.
Title: Re: Synapse TCP/IP client and server
Post by: PascalDragon on May 26, 2021, 08:57:46 am
as far as i know, UDP that is not guarantee that every packet is sent and received correctly.

Just to clarify: UDP does not guarantee delivery, however if it is delivered, it is delivered correctly (meaning without errors).

TCP/IP DOES guarantee that every packet is sent correctly altough packet sequence is not guaranteed.

Packet sequence is guaranteed with TCP (at the recipient, not during transit!), otherwise communication that relies on the order of the data (e.g. file downloads) wouldn't be possible without additional protocols.
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on May 30, 2021, 07:08:36 pm
If you find a way to improve RecvPacket please let me know, so I can integrate it in the test application.

Hello Getmem,

I checked the Synapse example code for a HTTPServer. There the header is received as string lines, each line is terminated with a line break (CR+LF). In Synapse there is a RecvString Function that calls RecvPacket repeatedly until the line break characters are found. The rest of a packet that is behind the line break is buffered within Synapse and returned the next time RecvBuffer is called. The size of the http-body is part of the headers and the body is then received with RecvBufferEx with predetermined size. This Synapse function calls RecvPacket in a loop until the defined number of bytes is received. The rest of the 'packet' (if the size doesn't exactly fit), again, is buffered back in Synapse. So both http-parts don't rely on any packets but determine the data size to be received on protocol level. And I think such mechanism is required when using TCP.

Packet sequence is guaranteed with TCP (at the recipient, not during transit!), otherwise communication that relies on the order of the data (e.g. file downloads) wouldn't be possible without additional protocols.
As said before, my understanding of TCP is that there are no packets at all exposed to the application but only a byte stream. So your mentioned file download only works if its size is known to the receiver, otherwise it couldn't determine when the transfer is complete. Is this correct?
Title: Re: Synapse TCP/IP client and server
Post by: PascalDragon on May 31, 2021, 01:09:33 pm
Packet sequence is guaranteed with TCP (at the recipient, not during transit!), otherwise communication that relies on the order of the data (e.g. file downloads) wouldn't be possible without additional protocols.
As said before, my understanding of TCP is that there are no packets at all exposed to the application but only a byte stream. So your mentioned file download only works if its size is known to the receiver, otherwise it couldn't determine when the transfer is complete. Is this correct?

On the network level it is composed of packets. The concept of data streams is built upon TCP, but in principle could also be built upon UDP.

And transmitting the length is not the only way to communicate the end of the stream: the sending side can simply terminate the TCP session once all data is send (this is in fact what's happening with HTTP downloads when the server does not transmit the size, though that's rather seldom nowadays).
Title: Re: Synapse TCP/IP client and server
Post by: delphi_coder on September 23, 2021, 01:42:19 am
As said before, my understanding of TCP is that there are no packets at all exposed to the application but only a byte stream. So your mentioned file download only works if its size is known to the receiver, otherwise it couldn't determine when the transfer is complete. Is this correct?
Here the word packet maybe a bit confusing, packet from your view differs by its meaning in network topic. All data traveling within TCP packets. There is no guarantee that you receive for example 3kb sent packet from the client at once, I think in most cases data checking and using Stream classes or implementing proper buffering is a must.
Title: Re: Synapse TCP/IP client and server
Post by: Ericktux on November 17, 2021, 05:13:47 am
excellent project friend getmem, thanks for sharing, two questions:
1. what does "broadcast" and "broadcasting" mean?
2. How can I get clients to talk to other clients and not to the server.

greetings friends  :)
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on November 17, 2021, 06:08:37 am
Hi Ericktux,

Quote
1. what does "broadcast" and "broadcasting" mean?
Select one ore more client + right click and you will see :)

Quote
2. How can I get clients to talk to other clients and not to the server.
You can't. This is not implemented. Shouldn't be to difficult to implement though.
Title: Re: Synapse TCP/IP client and server
Post by: piola on April 23, 2022, 01:38:42 pm
Hello,

I'm just trying your server example and have two points which are not clear to me:


Thanks for your help.
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on April 23, 2022, 02:39:03 pm
Hi piola,

Quote
1. TTCPServer.DisconnectClient only removes the client from the list, but it doesn't actually close the client's connection. Is this intended or is there something missing?
Inside DisconnectClient, method Remove is called, where the socket is closed:
Code: Pascal  [Select][+][-]
  1. TClientThread(AThread).FBlockSocket.CloseSocket;

Quote
The implementation of TClientThread.Execute seems to be responsible for both receiving data from the client and sending data from the server to the client. However, when the server has data waiting to be sent to the client (which is done in ProcessTask), these data will not be sent immediately, but have a delay because the receive timeout (in RecvMessage) always has to be awaited. How can I improve this so that responses from the server to the client are sent immediately?
Yes, I agree, this can be a problem. You can solve it by:
1. Creating more worker threads for time consuming operations like file transfer and streaming. Now there are 3 types:
Quote
TBaseType = (btClient, btServer, btServer_AcceptedClient)
You add more like btFileTransfer, btStreaming etc...For streaming you can switch to udp.

2. Create two TClientThread for each connection, one will be responsible for sending, one for receiving data
Both solution has pros and cons, I chose the first one in my application(unfortunately I cannot share the source code).

Quote
Thanks for your help.
Thanks for your comments.
Title: Re: Synapse TCP/IP client and server
Post by: piola on April 23, 2022, 03:07:56 pm
Hi, thanks for for quick response.

ad 1: I see, this has been a classical problem in my mind  ::) I interpreted the remove as belonging to the list, not to the TTCPServer class - shame on me.

ad 2: I think I will try the second suggestion. This should also simplify the TClientThread's execute method and I can use an event for resuming the "TSendClientThread"'s when data is available for sending.

Is it possible without causing trouble to use a separate TBlockSocket for the sending thread? I'm asking because both the receiving and the sending thread will have to use the same ports. I don't want the clients themselves to require two threads too because this would cause incompatibilities with other tools (in my case, especially telnet-Clients must be able to connect for debugging purposes).

It might also be possible that #2 is just a misuse of your component on my side. I'm using the TTCPServer's instance's SendMessage method for responding. I'm not sure whether this is correct. In my app, I have to separate the server logic from the protocol logic. All examples I have found for servers using TBlockSocket (e.g. a chat server somewhere else in this forum) do the response directly inside the client's Execute method. Of course, this is done for simplicity of the example, and indeed this makes creating a TCP server very simple, but I feel that things quickly get rather complicate when decoupling response handling from the server and taking into account that it might take a moment to prepare the response while everything should keep responsible in the meantime and no packets must get lost.

Overall, your server is very well designed and I hope it will work threadsafe even for a greater number of clients. I always have a some trouble in getting multithreading right, so your example has been of great value for me.
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on April 23, 2022, 04:42:45 pm
@piola

Quote
It might also be possible that #2 is just a misuse of your component on my side. I'm using the TTCPServer's instance's SendMessage method for responding. I'm not sure whether this is correct. In my app, I have to separate the server logic from the protocol logic. All examples I have found for servers using TBlockSocket (e.g. a chat server somewhere else in this forum) do the response directly inside the client's Execute method. Of course, this is done for simplicity of the example, and indeed this makes creating a TCP server very simple, but I feel that things quickly get rather complicate when decoupling response handling from the server and taking into account that it might take a moment to prepare the response while everything should keep responsible in the meantime and no packets must get lost.
The demo project was meant more for beginners. I designed SendMessage, SendStream and SendFile as a high level functions, so the users don't have to worry about implementation details. The server logic it is separated from the protocol logic via the TTaskList.  You can read more about it here: https://forum.lazarus.freepascal.org/index.php/topic,48677.msg406330.html#msg406330

Quote
so it possible without causing trouble to use a separate TBlockSocket for the sending thread? I'm asking because both the receiving and the sending thread will have to use the same ports. I don't want the clients themselves to require two threads too because this would cause incompatibilities with other tools (in my case, especially telnet-Clients must be able to connect for debugging purposes).
Slowdowns may occur if both the client and server sends large files for example at the same time. As I mentioned in my previous post, i solved this issue by creating more worker threads. However this does require more threads on the client side too. I don't see how you can solve it without extra threads no matter what solution do you choose. Since I don't know any details about you project, unfortunately I cannot give you any useful information.

Quote
Overall, your server is very well designed and I hope it will work threadsafe even for a greater number of clients. I always have a some trouble in getting multithreading right, so your example has been of great value for me.
Each client connection has a separate thread assigned at server side, so you shouldn't face problems even with a larger number of clients. At least in theory...again without knowing the details I cannot answer. I have a similar, not quite the same client/server application which is running for years, but I had to admit the workload on those application is relatively small.


PS: You should also give Indy a try. Many cool stuff are already implemented in Indy.

Title: Re: Synapse TCP/IP client and server
Post by: piola on April 23, 2022, 09:11:56 pm
Thank you again. I will try and report back whether it works.

My program uses a simple text-based communication protocol. Individual messages may be some 100 kB, but this case is rather rare. Typically, only a few 100 bytes are exchanged between client and server. In my case, it's more important to keep delays small.

I have already tried Indy and it worked quite well. But I had designed the server component not very well, so I decided to rewrite it. I read a lots of forum posts about how to do it properly. I tried the components that are included in FPC itself, but they didn't fit my needs (although at the moment I can't remember what the problem was). Your example seemed to be the best designed one, so I wanted to experiment with that. Please apologize for asking a question here and then, but I want to learn about using threads and networking.
Title: Re: Synapse TCP/IP client and server
Post by: piola on April 24, 2022, 01:16:52 am
Okay, I have a first feedback:

In utcpsockets.pas line 1270, I had to change if FTCPBase.FActiveOrConnected and FBlockSocket.CanRead(1000) then into if FBlockSocket.CanRead(1000) and FTCPBase.FActiveOrConnected then to avoid a deadlock on server termination.

Obviously, the call to Thread.FBlockSocket.CloseSocket in line 1736 causes FBlockSocket.CanRead in line 1270 to return with True which results in blocking in line 1283: the threadlist cannot be added to at this point because in parallel TServer.Cleanup has a lock on the list.

FActiveOrConnected should be False in the condition in line 1270 (it has been set to False in line 1753), but obviously, the check had been evaluated before while FActiveOrConnected had been True. The change to False occurs while waiting for FBlockSocket.CanRead. By swapping the order of evaluation, this issue seems to be fixed.

Btw: FActiveOrConnected is obiously written (in line 1753) to and read (in line 1270) in different threads. Why is there no need for a critical section?
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on April 24, 2022, 12:21:38 pm
2. The implementation of TClientThread.Execute seems to be responsible for both receiving data from the client and sending data from the server to the client. However, when the server has data waiting to be sent to the client (which is done in ProcessTask), these data will not be sent immediately, but have a delay because the receive timeout (in RecvMessage) always has to be awaited. How can I improve this so that responses from the server to the client are sent immediately?

I think you could change the timeout to zero, so only data that is already available will be fetched. I just checked the Synapse code, there is also a sleep(0) inside RecvPacket(), so the timeout won't be actually zero, but in a operating system there isn't such thing as "immediately" anyways, so that should be within range. (Perhaps it could be optimized a bit by just polling the available data.)
As I understand GetMem's code, a ping is always expected within the timeout and otherwise disconnects, so this would have to be decoupled e.g. by using the systick to identify if a ping wasn't received in time, seems something like that is included already.

Is it possible without causing trouble to use a separate TBlockSocket for the sending thread? I'm asking because both the receiving and the sending thread will have to use the same ports. I don't want the clients themselves to require two threads too [...].

You can only can establish one connection to the same ports, isn't!? So for a seperate sending TBlockSocket you would need an other connection. And in my understanding you also couldn't use two different threads directly accessing one TBlockSocket for sending and receiving (not thread safe). So to achieve full-duplex communication in Synapse you couldn't block receiving with timeouts, as said before. But I never tested if the library really supports full-duplex, sending data while a big download is done on the same connection.
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on April 24, 2022, 12:22:45 pm
By the way, in the meantime I stumbled over a article that describes the issue about the assumption of packets in TCP that I stated in a message earlier in this thread:
https://www.sobyte.net/post/2021-12/whys-the-design-tcp-message-frame/
Title: Re: Synapse TCP/IP client and server
Post by: PizzaProgram on April 24, 2022, 01:16:30 pm
I just wanted to report that:
 - Ararat Synapse's current latest trunk (R260) can handle OpenSSL3 well with TLS 1.3!

Here is an example how to send-and-receive JSON UTF8 strings with REST:
Code: Pascal  [Select][+][-]
  1. function HttpPostGetJSON(const URL: string; var JSON: UTF8String;const TimeOut: integer = 5000): Boolean;
  2. const
  3.     CRLF : UTF8String = #13#10;
  4. var
  5.     HTTP    : THTTPSend;
  6.     Data    : TStringStream;
  7. begin
  8.     HTTP := THTTPSend.Create;
  9.     Data := TStringStream.Create(JSON, TEncoding.UTF8);
  10.     JSON := '';
  11.     HTTP.Timeout := TimeOut;
  12.  
  13.     try
  14.         HTTP.Headers.Add('Content-Type: application/json; charset=UTF-8') ;
  15.         HTTP.Headers.Add('Accept: application/json') ;
  16.  
  17.         Data.Position := 0;
  18.       //Data.SaveToFile('C:\data.json');
  19.  
  20.         HTTP.Document.CopyFrom( Data, 0);
  21.         Data.Size := 0;
  22.         Result := HTTP.HTTPMethod('POST', URL);
  23.         if Result then begin
  24.             if HTTP.Document.Size > 0 then begin
  25.                 Data.LoadFromStream( HTTP.Document );
  26.                 JSON := Data.DataString + CRLF + 'Result=' + HTTP.ResultString + CRLF+ 'Protocol='+HTTP.Protocol ;
  27.                 // Data.UnicodeDataString
  28.             end;
  29.         end;
  30.     finally
  31.         HTTP.Free;
  32.         Data.Free;
  33.     end;
  34. end;

I think this function should be part of tzutil.pas .
Would be great if Synapse trunc would move to GitHub, so we can easier commit improvements too.

The one question remains:
- How to set unique Cert + Priv key ?
Code: Pascal  [Select][+][-]
  1. var
  2.   cert, priv_key: string;
  3. ...
  4.         HTTP.Sock.SSL.Certificate := cert ;
  5.         HTTP.Sock.SSL.PrivateKey  := priv_key;
  6.  
What encoding should they use? Hexa ? Base64?
Title: Re: Synapse TCP/IP client and server
Post by: piola on April 24, 2022, 09:05:06 pm
I have seized on the idea of GetMem using separate threads of sending and receiving. In my program I use a very slimmed-down variant of the original utcpsockets.pas, but I wanted to share the result so I have re-applied my changes to utcpsockets.pas.

@GetMem, maybe you might want to have a look on it whether the changes concord with your concepts. I tried to be as minimally invasive as possible.

@kupferstecher: I had thought about setting the timeout to zero, too, but that would be equal to polling, won't it? I want to avoid this situation because it consumes CPU-time for nothing.

About the ports, I'd have expected that it won't work. But my tests have been positive so far: the concept seems to work. I use two separate TBlockSockets configured with the same settings so they won't interfere with each other. And because on is only sending and the other one is only receiving, there should be no conflict on the socket either. However, I haven't tested high loads yet.
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on April 26, 2022, 06:40:00 am
Hi All,

Sorry for the late response I was away for a few days.

@piola
Quote
maybe you might want to have a look on it whether the changes concord with your concepts. I tried to be as minimally invasive as possible.
I will definitely check out your changes and don't worry about my concepts, feel free to modify the code in any way you like. The fact that you shared your changes it's a good thing. Thanks for that!

@kupferstecher
Quote
By the way, in the meantime I stumbled over a article that describes the issue about the assumption of packets in TCP that I stated in a message earlier in this thread:
https://www.sobyte.net/post/2021-12/whys-the-design-tcp-message-frame/
Thanks for the link, interesting article indeed.

@PizzaProgram
Not related to this thread, however I will update synapse in OPM soon. Is this a new release or still part of trunk? IIRC the last release was 40.1.
Title: Re: Synapse TCP/IP client and server
Post by: PizzaProgram on April 26, 2022, 09:57:01 am
@GetMem
Quote
Not related to this thread, however I will update synapse in OPM soon. Is this a new release or still part of trunk? IIRC the last release was 40.1.

It is the Latest Trunk R260: https://sourceforge.net/p/synalist/code/HEAD/tree/ (https://sourceforge.net/p/synalist/code/HEAD/tree/)
Sadly He did not change the version number from 40.1 to 50.0 or something, while it has major changes. I've suggested him to do that, but received no answer yet: 
https://sourceforge.net/p/synalist/bugs/62/ (https://sourceforge.net/p/synalist/bugs/62/)
Title: Re: Synapse TCP/IP client and server
Post by: kupferstecher on April 26, 2022, 01:09:38 pm
@kupferstecher: I had thought about setting the timeout to zero, too, but that would be equal to polling, won't it? I want to avoid this situation because it consumes CPU-time for nothing.
Yes, I'd call it polling then. But the application main loop also is polling, so the overhead should be very small. And a few CPU cycles each 10ms is nearly nothing.

Quote
I have seized on the idea of GetMem using separate threads of sending and receiving. In my program I use a very slimmed-down variant of the original utcpsockets.pas, but I wanted to share the result so I have re-applied my changes to utcpsockets.pas.

[...]

About the ports, I'd have expected that it won't work. But my tests have been positive so far: the concept seems to work. I use two separate TBlockSockets configured with the same settings so they won't interfere with each other. And because on is only sending and the other one is only receiving, there should be no conflict on the socket either. However, I haven't tested high loads yet.
After quickly checking your code, my understanding is that you use the same socket for both threads, which you pass when creating the threads:
Code: Pascal  [Select][+][-]
  1.   Socket := FBlockSocket.Accept; [...]
  2.   recvCT := TClientThread.Create(FTCPBase, Socket); [...]
  3.   sendCT := TClientThread.Create(FTCPBase, Socket);

And I don't think Synapses sockets are thread save in that way, but I'm not sure.
Title: Re: Synapse TCP/IP client and server
Post by: Sharfik on September 01, 2022, 12:34:48 am
Can not understand. Why is the list of users separately made a simple list. And why send all the processing of message events for the server to the main thread?
Title: Re: Synapse TCP/IP client and server
Post by: datilas on January 09, 2023, 04:09:26 pm
using application GUI works great,
but i am trying to create a daemon service
with the daemon service the service activates normally.
but when I connect with the client returns the error:
"Invalid username or password.(10013)"
Has anyone tried using it as a daemon service?
Can someone help me?

....

in console application the same problem happens
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 05, 2023, 04:20:32 pm
@datilas
I don't know if it helps to identify the problem but I got the same error when I tried to add both server and client parts to the same application. When I enter the correct login data, however, I get error "Invalid username or password (10013)" in the client form while on the server form, after confirming the connection, it immediately disconnects with error "Connection reset by peer (10054)"

about communication with windows services some time ago I read on this link https://stackoverflow.com/questions/4451216/how-to-communicate-with-a-windows-service but it probably has nothing to do with it and I can't confirm it: "..with Windows Vista, services can no longer interact directly with users, i.e., no user interfaces.."

@GetMem
In any case thanks for this implementation which I found useful  :)
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 06, 2023, 09:35:00 pm
I tested version 2.0.12 but unlike version 2.0.10, the client freezes, if while I send a file I go to send something else as a text message. The server receives the file but the client stops responding.
For the test I used a file slightly larger than a gb while for the text only one word. Always reproducible.

Windows 10 64bit
Laz 2.2.4 64bit FPC 3.2.2

Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 06, 2023, 09:52:00 pm
I tested version 2.0.12 but unlike version 2.0.10, the client freezes, if while I send a file I go to send something else as a text message. The server receives the file but the client stops responding.
For the test I used a file slightly larger than a gb while for the text only one word. Always reproducible.

Windows 10 64bit
Laz 2.2.4 64bit FPC 3.2.2
Hi Phoenix,

@piola made some improvement, see attachment from reply #35.  Does it help? If not I will take a look.

PS: I plan to rewrite the whole thing, with a slightly different paradigm. Unfortunately I don't have much free time.
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 06, 2023, 10:52:08 pm
Hi @GetMem I replaced the utcpsockets.pas file in your version 12. I can connect but the send doesn't send anything (not even failure messages). If I close the client, I get a double disconnect message on the server.

Out of curiosity I tried the modified client with your original server but it doesn't change the result except that I rightly get only one disconnect message when I close the client.

I know that client and server are designed to run on different executables but with the version already available, is it possible to run them on the same executable? The idea would be that each exe has a chance to become server when the active server is shut down. But the exe that will have the active server does not allow you to connect the clients unfortunately.

In any case version 10 for what I need is sufficient and working  :).
Thank you
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 07, 2023, 06:28:47 am
@Phoenix
Quote
know that client and server are designed to run on different executables but with the version already available, is it possible to run them on the same executable? The idea would be that each exe has a chance to become server when the active server is shut down. But the exe that will have the active server does not allow you to connect the clients unfortunately.
I don't see an easy way to achieve this. However you can communicate between the server and local client.

Quote
In any case version 10 for what I need is sufficient and working  :).
Thank you
You're welcome!
Title: Re: Synapse TCP/IP client and server
Post by: datilas on February 07, 2023, 07:26:24 pm
using application GUI works great,
but i am trying to create a daemon service
with the daemon service the service activates normally.
but when I connect with the client returns the error:
"Invalid username or password.(10013)"
Has anyone tried using it as a daemon service?
Can someone help me?

....

in console application the same problem happens

from what I understand is a problem with TThread, which both with daemon and console works differently compared to LCL.
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 07, 2023, 07:59:45 pm
@datilas
Quote
from what I understand is a problem with TThread, which both with daemon and console works differently compared to LCL.
Windows:
Since windows vista(circa 2007) a service cannot interact with the desktop, meaning you cannot show forms, messages like you would from a regular application. The so called session 0 isolation was introduced for security reason. If you would like to run the server as service, you have to get rid of the visual components. This is easy because de business and UI logic are well separated. You have to move the UI logic to a standard application and communicate with the service/server via sockets, pipes, named pipes, memory mapped files, etc.

Linux:
Unfortunately I have no idea if a daemon can interact with the desktop under linux. Most likely not.
Title: Re: Synapse TCP/IP client and server
Post by: datilas on February 08, 2023, 07:57:17 pm
@datilas
Quote
from what I understand is a problem with TThread, which both with daemon and console works differently compared to LCL.
Windows:
Since windows vista(circa 2007) a service cannot interact with the desktop, meaning you cannot show forms, messages like you would from a regular application. The so called session 0 isolation was introduced for security reason. If you would like to run the server as service, you have to get rid of the visual components. This is easy because de business and UI logic are well separated. You have to move the UI logic to a standard application and communicate with the service/server via sockets, pipes, named pipes, memory mapped files, etc.

Linux:
Unfortunately I have no idea if a daemon can interact with the desktop under linux. Most likely not.

I want to put the server with service in linux
and the client with a gui application

the issue is there will be no interaction with the user on the server, only on the client.

so i would like to run the server as daemon or console.
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 08, 2023, 08:37:03 pm
@datilas
Quote
I want to put the server with service in linux
and the client with a gui application

the issue is there will be no interaction with the user on the server, only on the client.

so i would like to run the server as daemon or console.
Then remove every visual component from the server and you are good to go.
Title: Re: Synapse TCP/IP client and server
Post by: datilas on February 08, 2023, 10:40:11 pm

Then remove every visual component from the server and you are good to go.
this I already did and the error of my first post occurs (Reply #40)
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 09, 2023, 08:56:13 am
@datilas
Quote
this I already did and the error of my first post occurs (Reply #40)
"Invalid username or password.(10013)"

Did you provide a password for the server? Something like this:
Code: Pascal  [Select][+][-]
  1. function TDaemon.Start: Boolean;
  2. var
  3.   BindConnection: TConnection;
  4. begin
  5.   Result := inherited Start;
  6.   Application.Log(etDebug, 'Starting server.');
  7.   FTCPServer := TTCPServer.Create;
  8.   FTCPServer.HideErrorMessages := True;
  9.   FTCPServer.HideInternalMessages := True;
  10.   try
  11.     BindConnection := TConnection.Create;
  12.     BindConnection.FIP := '0.0.0.0';
  13.     BindConnection.FPort := '40516';
  14.     BindConnection.FPass := 'daemonpass'; //<-this line
  15.     FTCPServer.Start(BindConnection);
  16.   finally
  17.     BindConnection.Free;
  18.   end;
  19.   Application.Log(etDebug, 'Daemon started.');
  20. end;    

I attach a version where the server is a daemon(only tested on windows).
Title: Re: Synapse TCP/IP client and server
Post by: datilas on February 09, 2023, 03:15:06 pm
@datilas
Quote
this I already did and the error of my first post occurs (Reply #40)
"Invalid username or password.(10013)"

Did you provide a password for the server? Something like this:


I attach a version where the server is a daemon(only tested on windows).

this example accepts only one connection.
the second connection returns the same error.
"Invalid username or password. (10013)"


tested on windows 10 and windows 7
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 09, 2023, 04:20:15 pm
@datilas

Most likely the server freezes for some reason, you have to debug it.
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 15, 2023, 06:08:41 pm
Hi @GetMem I tried to edit your project but I ran into a problem. In the attached application I have inserted a menu item "File > Test" on the server side to send n messages in broadcast but the client does not receive all the messages sent by the server. I made some changes in utcpsockets.pas but the already available features seem to work even with the changes.. :-\
ps. I used laz.VirtualTrees and disabled internal messages from usettings because the client (launched on lazarus) returned a read error when used during testing. Maybe GUI calls need to be "protected"?

Windows 10 64bit
Laz 2.2.4 64bit FPC 3.2.2
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 15, 2023, 07:21:36 pm
Hi @GetMem I tried to edit your project but I ran into a problem. In the attached application I have inserted a menu item "File > Test" on the server side to send n messages in broadcast but the client does not receive all the messages sent by the server. I made some changes in utcpsockets.pas but the already available features seem to work even with the changes.. :-\
ps. I used laz.VirtualTrees and disabled internal messages from usettings because the client (launched on lazarus) returned a read error when used during testing. Maybe GUI calls need to be "protected"?

Windows 10 64bit
Laz 2.2.4 64bit FPC 3.2.2
You are on the right track, protecting with CriticalSection is not enough though, you have to wait until the lock is lifted, before you can add or remove a task. The attached solution works, but is far from ideal.

PS: I'm working on a second edition...
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 15, 2023, 09:04:35 pm
You are on the right track, protecting with CriticalSection is not enough though, you have to wait until the lock is lifted, before you can add or remove a task. The attached solution works, but is far from ideal.

PS: I'm working on a second edition...

Indeed the test works  :). But trying to send a file, the client freezes (see reply #42).

Thanks and sorry for the extra work
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 15, 2023, 09:58:03 pm
Quote from: Phoenix
Indeed the test works  :). But trying to send a file, the client freezes (see reply #42).

Thanks and sorry for the extra work
The pinging mechanism was also effected by your modification. Please try again, I don't see any freezing now.
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 16, 2023, 04:11:59 pm
The pinging mechanism was also effected by your modification. Please try again, I don't see any freezing now.

Ok thanks, it works almost perfectly  :). It no longer freezes "permanently" so requests are all accepted. But if I send a file large enough to allow me to send a simple message, when I press "send", the client becomes unresponsive until the download to the server has finished.

From what you wrote, it doesn't happen to you. From code the call to SendMessage is directed on thread so shouldn't it leave the button in the "pressed" state and not allow me to move the form?
However, the problem is keeping the tasklist locked for too long. So I edited again:

Code: Pascal  [Select][+][-]
  1.     if (not FNeedToBreak) and (not FTaskList.FBlocked) then//#
  2.     begin
  3.        //mod
  4.        FTaskList.Lock;
  5.        try
  6.          if not FTaskList.IsEmpty then
  7.          begin
  8.            ProcessTask(TTask(FTaskList.FList[0]));
  9.            FTaskList.DeleteFirst;//.FList.Delete(0);
  10.          end;
  11.        finally
  12.          FTaskList.Unlock;
  13.        end;
  14.     end;
  15.  

with this

Code: Pascal  [Select][+][-]
  1.     if (not FNeedToBreak) and (not FTaskList.FBlocked) then
  2.       //#
  3.       if FTaskList.GetNextTask(CurrTask{%H-}) then
  4.       begin
  5.         ProcessTask(CurrTask);
  6.         CurrTask.Free;
  7.       end;
  8.  

It seems to work fine but I don't know if there is anything else to consider..
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 16, 2023, 04:52:45 pm
@Phonix
Quote
Ok thanks, it works almost perfectly  :). It no longer freezes "permanently" so requests are all accepted. But if I send a file large enough to allow me to send a simple message, when I press "send", the client becomes unresponsive until the download to the server has finished.
Please note that synapse use blocking sockets, with limited support for non-blocking mode. While you send a large file you cannot send a text in parallel, unless you spawn another worker thread both on the client end server side, just for the file transfer. I can make the client  more responsive(see attachment), but the transfer won't be faster.
You can even complicate things by sending a large file from client to server and in the same time another large file from server to client. It won't work in parallel either in the current implementation.

Quote
It seems to work fine but I don't know if there is anything else to consider..
Code: Pascal  [Select][+][-]
  1. if (not FNeedToBreak) and (not FTaskList.FBlocked) then
  2.       //#
  3.       if FTaskList.GetNextTask(CurrTask{%H-}) then
  4.       begin
  5.         ProcessTask(CurrTask);
  6.         CurrTask.Free;
  7.       end;
The task list is not locked, one ore more task can be overwritten or deleted. Even if you manage to copy the next task in a safe way, ProcessTask won't work faster, you need extra threads.
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 16, 2023, 06:40:40 pm
Please note that synapse use blocking sockets, with limited support for non-blocking mode. While you send a large file you cannot send a text in parallel, unless you spawn another worker thread both on the client end server side, just for the file transfer. I can make the client  more responsive(see attachment), but the transfer won't be faster.
You can even complicate things by sending a large file from client to server and in the same time another large file from server to client. It won't work in parallel either in the current implementation.
Yes, synchronicity is the strong point. The goal was just to send tasks when you want without blocking the button.

The task list is not locked, one ore more task can be overwritten or deleted. Even if you manage to copy the next task in a safe way, ProcessTask won't work faster, you need extra threads.
You're right, the lock in GetNextTask() is not enough because it must be maintained for the entire execution. Thank you  :)
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 16, 2023, 09:18:51 pm
@Phoenix
Quote
You're right, the lock in GetNextTask() is not enough because it must be maintained for the entire execution.
Actually GetNextTask is safe, somehow I missed the function body. Sorry for that! What I said in my previous post still holds though, the client/server communication won't be faster.
Also I implemented a much better, non blocking way to add task to tasklist, Application.ProcessMessages is not neeeded. Search for function AddTaskInThread, I did not test it extensively, it might contain bugs/leaks. Please test it.

PS: If you wish to improve the code, I have a few more ideas(unfortunately almost no free time).
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 17, 2023, 01:09:01 am
Hi @GetMem,
Actually GetNextTask is safe, somehow I missed the function body. Sorry for that!
It is OK. But even my answer shows that I don't know much about synapse  :-[.. otherwise maybe I would have insisted more  ;)

I did not test it extensively, it might contain bugs/leaks. Please test it.
thanks  :), the code seems to work as expected. With the previous modifications a memory leak was introduced, now I fixed it (see attachment).

PS: If you wish to improve the code, I have a few more ideas(unfortunately almost no free time).
Ideas are always welcome, then for the implementation one always hopes not to be alone. I think that those who benefit from your demo can contribute in turn according to their possibilities.
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 17, 2023, 08:48:37 am
@Phoenix

Quote
Ideas are always welcome, then for the implementation one always hopes not to be alone. I think that those who benefit from your demo can contribute in turn accordingto their possibilities.
Ideas:
1. When accessing FThreadList(TThreadList) in TTCPBase class, the following mechanism is used:
Code: Pascal  [Select][+][-]
  1.   List := FThreadList.LockList;
  2.   try
  3.     //..
  4.   finally
  5.     FThreadList.UnlockList;
  6.   end;        
Which is fine, but not enough. With the current method, if more then one client is connecting at the same time, the server might miss a few clients. Another Lock/Unlock mechanism should be implemented, similar to the one in TTaskList, using CriticalSections and the FBlocked boolean. TThreadList can be replaced with a simple TList because it will be protected with CS.
This is a bug and should be fixed.
2. Create working threads for filetransfer, to make both client/server faster and more responsive. @piola already implemented something similar in reply #35
3. Fixing the daemon/service issue, @datilas post in reply #52
4. Switching from TCP to UDP when broadcasting
5. Implement UDP hole punching
6. Create a github/gitlab/bitbucket/sourforge(/ = or) repository. Currently we are ping-ponging with the source files, like we did in the '90. It' s so unprofessional and dirty, I almost enjoying it. :D Seriously though we need a repository. I have enough on my plate with OPM, it would be really nice if somebody could take care of the repository.

I attach the whole project again, with the same uTCPServer unit from your last post, minus a few comments("//#") , those are not needed anymore.
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 17, 2023, 07:21:30 pm
Currently we are ping-ponging with the source files, like we did in the '90. It' s so unprofessional and dirty, I almost enjoying it. :D

For now let's continue with the fun  :D, why stop  ;)? but I agree that a repository is needed.

1. When accessing FThreadList(TThreadList) in TTCPBase class, the following mechanism is used:
Code: Pascal  [Select][+][-]
  1.   List := FThreadList.LockList;
  2.   try
  3.     //..
  4.   finally
  5.     FThreadList.UnlockList;
  6.   end;        
Which is fine, but not enough. With the current method, if more then one client is connecting at the same time, the server might miss a few clients. Another Lock/Unlock mechanism should be implemented, similar to the one in TTaskList, using CriticalSections and the FBlocked boolean. TThreadList can be replaced with a simple TList because it will be protected with CS.
This is a bug and should be fixed.

I attach the code that hopefully solves but there are some doubts that I signaled with "#"

P.S.
I forgot I saw that in the classes many variables are not "initialized". I was wondering, if you use some compiler optimization options maybe they are no longer "set to zero"? I personally always initialize everything

Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on February 17, 2023, 08:27:38 pm
@Phoenix

Thanks for the modifications!

Quote
I attach the code that hopefully solves but there are some doubts that I signaled with "#"
Everything looks fine, except when two clients simultaneously disconnect and the threads are removed from the servers list. It looks to me that the first thread will lock the list and the second one will be ignored. The "If not FBlocked then ..." condition is missing. Unfortunately in this particular case it's very hard to check for FBlocked without slowing down the main thread. I still have an uncontrollable urge to rewrite the whole thing, it would be much easier this time, because I learned from my mistake.

Quote
I personally always initialize everything
Good practice! I tend to cheat and initialize only what is absolutely necessary. Most of the time I get away with it without any issues.
Title: Re: Synapse TCP/IP client and server
Post by: Phoenix on February 18, 2023, 09:56:16 am
I still have an uncontrollable urge to rewrite the whole thing, it would be much easier this time, because I learned from my mistake.

If you already have clear ideas then the result will be better. Subsequent steps will probably make the code less maintainable because you need to constantly adapt. So feel free to rewrite when you find the time.

I tend to cheat and initialize only what is absolutely necessary. Most of the time I get away with it without any issues.

Nice to be so lucky  ;), unfortunately I have had opposite educational experiences  :D. However consider the idea in your rewrite so the code will be more robust.

Everything looks fine, except when two clients simultaneously disconnect and the threads are removed from the servers list. It looks to me that the first thread will lock the list and the second one will be ignored.

Among the ideas perhaps you should consider a unit test. Simulating the worst cases can go a long way in gaining free time  :).
Title: Re: Synapse TCP/IP client and server
Post by: balazsszekely on March 30, 2023, 02:27:28 pm
Moved to: https://forum.lazarus.freepascal.org/index.php/topic,62874.msg475673.html#msg475673
TinyPortal © 2005-2018