mitzi 43 Posted December 27, 2019 ICS v8.63 hi, I have TSslWSocketThrdServer and TSslWSocket. When server is not active (listening) and client tries to connect, following sequence of state changes is triggered: State changed: wsClosed->wsOpened State changed: wsOpened->wsConnecting State changed: wsConnecting->wsConnected State changed: wsConnected->wsClosed Why wsConnected is triggered? It is not true, client cannot be connected even for a while when server is down. It causes big problems when I want to get client reconnected in case of connection lost (or initially not available). I try to connect (in thread) and I get state wsConnected, thread is terminated because connection seems to be established but it is not. Can you fix it? In my opinion it should trigger wsConnecting->wsClosed as a last state change. Thanks. Share this post Link to post
Angus Robertson 577 Posted December 27, 2019 Why does any of this matter, this is a listening server and there is no thread until after a client connects successfully, which you see from the OnClientConnect event. The server state should always be wsListening. BTW, TSslWSocketThrdServer has now been updated or tested for many years, although it descends from TWSocketServer which is heavily used and updated. Angus Share this post Link to post
mitzi 43 Posted December 27, 2019 I'm talking about client states, not server. Sequence is taken from TSslWSocket.OnChangeState event. Share this post Link to post
Angus Robertson 577 Posted December 27, 2019 Again why does it matter? The client has already connected to the server by the time the client socket is created and the OnClientConnect event has been triggered. SocketState is only used by the component to check if the socket needs to closed, there is no connecting state concept for a server listening socket. Angus Share this post Link to post
mitzi 43 Posted December 27, 2019 Well. Maybe we dont understand each other. How can I recognize that tcp client is connected to server? On client side? There’s no property except State. Share this post Link to post
Angus Robertson 577 Posted December 27, 2019 The OnClientConnect event I've mentioned twice is how you know the client is connected. TSslWSocketClient is not created until after connection is successful, although SSL negotiation may still fail so the socket gets disconnected again. Servers only ever listen and respond to commands from remote clients, most clients will cleanly disconnect once completed, but you generally don't know if the client is still there which is why most servers have a timeout for an idle client. Angus Share this post Link to post
FPiette 385 Posted December 28, 2019 Quote How can I recognize that tcp client is connected to server? On client side? On client side, you have the event OnSessionConnected triggered with an error argument being zero. If client can't connect to server, you still have the same OnSessionConnected event triggered but with an error argument not zero, for example 10061 which means the server is not running at the IP/Port/protocol specified. Use state property only for display or log. Use events for everything that "happens" such as connection established or closed or data available and more. Read the comment "About multithreading and event-driven" in OverbyteIcsWSocket.pas (The main source of the sockect component). Share this post Link to post
Angus Robertson 577 Posted December 28, 2019 Should have said earlier the main event that tells you a client is connected is receiving data in the onDataAvailable in TSslWSocketClient, this is where any data from the remote client arrives. You assign this even in the OnClientConnect event. Very unusual for a server to initiate sending data to a client without receiving something first, even a blank line. Angus Share this post Link to post
mitzi 43 Posted January 3, 2020 (edited) Is it possible to use TSslWSocketThrdClient descendant instead of TSslWSocket on client side? I tried and it worked except one thing. OnSessionClosed is triggered only once and then never again. Edited January 3, 2020 by mitzi Share this post Link to post
Angus Robertson 577 Posted January 3, 2020 If you are using TSslWSocketThrdServer then you should be using TSslWSocketThrdClient. However TSslWSocketThrdServer is itself a descendent of TSslWSocketServer which does not use threads, so it all depends on how you are using the component. OnSessionClosed is only gone to triggered once since the client is destroyed immediately afterwards. Presumably you started with the OverbyteIcsThrdSrvV3.dpr sample which is the documentation and sample for TSslWSocketThrdServer, but does not support SSL. Angus Share this post Link to post
mitzi 43 Posted January 9, 2020 Another question: Is there some timeout for connection attempt? When TWSocket tries to connect to server and server does not exist (non-existing ip address or non-listening server) it takes 20 secs than OnSessionClosed is triggered. Can this timeout be changed/set? Thanks for your support Share this post Link to post
Angus Robertson 577 Posted January 9, 2020 I assume you are now talking about clients and not servers? Simple answer is no, TCP is a lazy protocol based on waiting for responses from slow networks (decades ago) so nothing happens fast. Long answer is Windows allows you to change the TCP timeouts, but such changes effect all applications on the PC and generally it's a very bad idea. Real solution is to try and ping the server before connecting using TCP, because you can timeout after a few seconds and give up. ICS has a threaded ping component for this purpose. and a high level client/server component TIcsIpStrmLog that uses ping for exactly this purpose. TIcsIpStrmLog may be configured as a client or server and allows simple text lines to sent, using few lines of code in the application and only a couple of events. There is a sample OverbyteIcsIpStmLogTst.dpr that send packets to itself. The component supports SSL and will order it's own certificates. Only problem with ping is sometimes it's blocked by firewalls so no response. You can use a UDP server in parallel with the TCP server for a quick hello, no response is similar to ping. Angus Share this post Link to post
FPiette 385 Posted January 9, 2020 It is also possible to use a TTimer for desired timeout and call Albort against the socket waiting for connection. Share this post Link to post
Fr0sT.Brutal 900 Posted January 10, 2020 Ehm... guys why so complicated, TWSocket inherits from TCustomTimeoutWSocket if BUILTIN_TIMEOUT define is set so it has both connect timeout and idle timeout. Share this post Link to post
Angus Robertson 577 Posted January 10, 2020 TCustomTimeoutWSocket timeouts relate to a socket that is already opened and connected, primarily a server socket, not to TCP DNS and connection attempts. As Francois says, you can use a timer to abort the connection, but this does not stop the windows connection attempt so the socket can not be re-used immediately for another attempt. Angus Share this post Link to post
mitzi 43 Posted January 10, 2020 If ICS uses WinSock.Select for connection then timeout can be set via latest parameter. Look at following code sample. I modified method from Delphi System.Win.ScktComp.pas and it does exactly what I want. Sets timeout for connection attempt to 5 secs. Originally it took 20 secs too. But I can't use these components :(. procedure TCustomWinSocket.DoOpen; var v: integer; WrSet : TFDSet; TimeVal : TTimeVal; begin DoSetASyncStyles; Event(Self, seConnecting); v:=1; IOCtlSocket(FSocket,FIONBIO,v); try CheckSocketResult(Winapi.WinSock.connect(FSocket, FAddr, SizeOf(FAddr)),'connect'); TimeVal.tv_sec:=5; TimeVal.tv_usec:=0; FD_ZERO(WrSet); FD_SET(FSocket,WrSet); if Select(0,nil,@WrSet,nil,@TimeVal)<>1 then CheckSocketResult(1,'select'); finally v:=0; IOCtlSocket(FSocket,FIONBIO,v); end; FLookupState := lsIdle; if not (asConnect in FAsyncStyles) then begin FConnected := FSocket <> INVALID_SOCKET; Event(Self, seConnect); end; end; Couldn't be something like this implemented to ICS? Share this post Link to post
Angus Robertson 577 Posted January 10, 2020 If you want to write your own internet library for your own requiremets, please feel free. Angus Share this post Link to post
mitzi 43 Posted January 10, 2020 No I don't have this intent. I found ICS very usable, but this is, in my opinion, key property ICS should have. I just wanted to point that this timeout is possible to be set. You wrote it is not possible by design. It seems it is not true. So my question is whether it is possible to implement this timeout setting to ICS? Consider this situation. I have primary TCP server and backup TCP server. Clients are connected to primary one. If this primary server goes down for any reason, then client loses connection and tries to reconnect. But it can take 20 secs now than it finds server is really inaccessible and then connects to backup server. This reconnection should be as short as possible. Mostly if client is not able to connect within 5 secs server can be considered as inaccessible and then connection to another backup server is processed. But 20 secs is really too long. Your recommendations how to solve this problem when connection timeout cannot be set? Share this post Link to post
Angus Robertson 577 Posted January 10, 2020 I have already given my suggestions on how to solve very common issue. If you need new features you have the ICS source and you can update it yourself. Or listen to those of us that have been using it for 20 years. Angus Share this post Link to post
mitzi 43 Posted January 10, 2020 (edited) Your suggestions are no usable. ICMP is security issue and it is no allowed in our environment. Also it only checks IP address accessibility. Not TCP server itself. Other suggestions does not allow the socket to be immediately reused for new connection attempt. Do you really think my request is so stupid? Edited January 10, 2020 by mitzi Share this post Link to post
Fr0sT.Brutal 900 Posted January 10, 2020 Why reusing sockets is so important? Do you really have 100000 of active socket handles on the client side? Share this post Link to post
mitzi 43 Posted January 10, 2020 If client connect attempt to primary server fails, it needs immediately to connect to another one. If socket is in use even after timer 'breaks' connection attempt by Abort, then next immediate attempt will fail too due to socket is in use, won't it? Share this post Link to post
Angus Robertson 577 Posted January 10, 2020 I've explained the limitations of the TCP implementation on Windows and how to get around it. If you don't want to listen to my experience, feel free to Google for better solutions then let us know when you have a proven working solution. Many of us have done all this before, often several times. Angus Share this post Link to post
mitzi 43 Posted January 10, 2020 (edited) Well but this is what I ask for. How did you (or others) solve this scenario? Your suggestion is ping. Well, when ping is successful it tells me nothing about my TCP server, if it is running and listening or not. Other suggestion is to abort connection attempt with timer. But it creates new problem with socket reusing. So what? It seems there's no useful advice. I will try to make my own port scan via WinSock.Select with timeout set to 5 secs (as I did in my post above for Delphi Socket component) before TWSocket.Connect. Disadvantage is when server is on, then i will do two connection attempts. First by port scan and second with real client connect. Another one is that this is blocking attempt. 😞 Anyone has better solution? Edited January 10, 2020 by mitzi Share this post Link to post
Fr0sT.Brutal 900 Posted January 10, 2020 (edited) 3 hours ago, mitzi said: If client connect attempt to primary server fails, it needs immediately to connect to another one. If socket is in use even after timer 'breaks' connection attempt by Abort, then next immediate attempt will fail too due to socket is in use, won't it? Well, probably I'm getting it wrong but I see no problem here SockObj creates socket handle = $111 SockObj tries to connect SockObj gets timeout SockObj closes socket handle = $111 and has its internal field FSockHandle set to -1 SockObj creates socket handle = $222 SockObj tries to connect ... some time later socket handle = $111 really closes and becomes available to the next use Edited January 10, 2020 by Fr0sT.Brutal Share this post Link to post