7

I am using TTCPBlockSocket for a TCP/IP Application . The problem is that I can't determine when the connection is lost.

GetLastError returns 0
Read returns 0

But I encounter these values eaven if the application is connected so I can get it how can I be notified when the TCP/IP connection is lost.

Thanks

Thom A
  • 88,727
  • 11
  • 45
  • 75
opc0de
  • 11,557
  • 14
  • 94
  • 187
  • I'd say the [`CanRead`](http://synapse.ararat.cz/doc/help/blcksock.TBlockSocket.html#CanRead) function call passing 0 as `Timeout` parameter is what you're looking for. This function internally calls `InternalCanRead` which performs the Winsock [`select`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx) function. The `CanRead` function returns False if any error occurs. – TLama Oct 24 '12 at 09:32
  • @TLama your answer led me to the right path tough the following condition must be met to check if it is disconnected if TCPBlockSocket.CanRead(0) and TCPBlockSocket.WaitingData = 0 the disconnected := true. You can post this as an answer for me to accept – opc0de Oct 24 '12 at 09:55
  • @TLama is the synapse expert ! – PFeng Jan 20 '13 at 07:06

3 Answers3

1

I would say, you can use the CanRead method, passing 0 to its Timeout parameter. This function internally performs select function for the socket and returns False when an error occurs. It should be enough to use just this method since the select function returns SOCKET_ERROR if you lose the connection, and it causes the CanRead method return False as a result. So I think, it's enough to check if the socket connection is alive this way:

function IsSocketAlive(ASocket: TTCPBlockSocket): Boolean;
begin
  Result := ASocket.CanRead(0);
end;
TLama
  • 75,147
  • 17
  • 214
  • 392
  • Nope is not enough test it yourself +1 for this – opc0de Oct 24 '12 at 16:44
  • The `WaitingData` method (as you added) returns the amount of data pending in the network's input buffer, and if that internal `ioctlsocket` function call doesn't fail with the `SOCKET_ERROR` and returns the pending data amount at the time when your connection is already lost, then it doesn't reflect your needs. Or am I wrong ? (unfortunately, I can't test it now) – TLama Oct 24 '12 at 17:24
1

As opC0de says, to check if the client is still connected you need to both check TCPBlockSocket.CanRead(0) and TCPBlockSocket.WaitingData = 0

function IsSocketAlive(ASocket: TTCPBlockSocket): Boolean;
begin
  Result := (ASocket.Socket = INVALID_SOCKET) or ((ASocket.WaitingData = 0) and ASocket.CanRead(0));
end;

I'm using this way in my projects so I can confirm that it works.

kattunga
  • 51
  • 1
  • 6
0

I was using kattunga's answer, but encountered a lot of false positive triggers during my stress test. My assumption is that the packet will sometimes arrive at a server between WaitingData and CanRead conditions, leading to server thinking that a socket is dead. I changed the order of conditions and problem was gone.

function TTCPSynWorkThread.IsSocketDead(ASocket: TTCPBlockSocket): boolean;
begin 
  Result := (ASocket.Socket = INVALID_SOCKET) or (ASocket.CanRead(0) and (ASocket.WaitingData = 0));
end;
Mozzg
  • 9
  • 1
  • 3