Turan Can 3 Posted February 6, 2020 (edited) Hello everyone, How do we constantly check whether there is a connection in a TCP/IP connection? windows sample, With what can I get android connection status? POSIX function TGateSocket.IsConnected: Boolean; var FDSet: Fd_Set; Tv: TimeVal; I: Integer; begin Result := False; FD_ZERO(FDSet); _FD_SET(SockId, FDSet); Tv.tv_sec := 0; Tv.tv_usec := 500; {$IFDEF MSWINDOWS} I := select(0, @FDSet, nil, nil, @Tv); if (I = SOCKET_ERROR) then Result := False else if recv(FSockId, FDSet, -1, 0) = 0 then Result := False else Result := True; {$ENDIF} {$IFDEF POSIX} ?? {$ENDIF} end; Edited February 6, 2020 by Turan Can Share this post Link to post
Fr0sT.Brutal 900 Posted February 6, 2020 AFAIK this set of socket functions is identical in Win and Nix (both from Berkeley sockets). I'm curious, what do you do by recv() with length=-1? Share this post Link to post
Turan Can 3 Posted February 6, 2020 I have "recv -1" data, I check this. so I see if there is data or not :). It's a nice method. Share this post Link to post
Turan Can 3 Posted February 6, 2020 FD_ZERO(FDSet); _FD_SET(SockId, FDSet); Tv.tv_sec := 0; Tv.tv_usec := 0; I := select(0, @FDSet, nil, nil, @Tv); I - I look before the connection. result = 0 sock.. connect.. I - After connecting, I see the result is still the same. result = 0 Share this post Link to post
Remy Lebeau 1396 Posted February 6, 2020 15 hours ago, Turan Can said: How do we constantly check whether there is a connection in a TCP/IP connection? Cross-platform, the only way is to perform an I/O operation on the socket and check for error. On Windows, at least, a non-blocking socket can issue an asynchronous FD_CLOSE notification when the connection is closed, but you should still check I/O operations for errors, too. 15 hours ago, Turan Can said: windows sample, With what can I get android connection status? POSIX The same type of coding will work on POSIX, too. The base BSD socket API, like select() and recv(), is common across multiple platforms. 15 hours ago, Turan Can said: I := select(0, @FDSet, nil, nil, @Tv); if (I = SOCKET_ERROR) then Result := False else if recv(FSockId, FDSet, -1, 0) = 0 then Why are you passing your fd_set variable as the buffer for recv() to read into? More importantly, you can't pass -1 as the size of the buffer to read into. On Windows, the len parameter is an int, so it will at least compile with a length of -1, but semantically asking recv() to read -1 number of bytes makes no sense, and is not documented as a supported operation. But worse, on other platforms, the len parameter is a size_t, which is an unsigned type, so passing in a length of -1 will wrap to a very large value and very bad things can happen! Also, you are not checking to make sure that select() actually reports the socket is readable before then calling recv() on the socket. Since you are only querying 1 socket, the return value of select() will be -1 on error, 0 on timeout (not readable), and 1 (readable). Alternatively, since select() modifies the fd_set struct on output, you can check if your socket is still in the set after select() exits. Also, you are not handling recv() reporting an error at all. Either way, do keep in mind that you are performing an actual read, so any bytes that recv() does actually receive will not be available for subsequent reads, so you will have to buffer the bytes somewhere in memory so you can still use them later. In most cases, implementing an IsConnected() type of function is really unnecessary and should be avoided. 1 Share this post Link to post
Remy Lebeau 1396 Posted February 6, 2020 (edited) 13 hours ago, Turan Can said: I have "recv -1" data, I check this. so I see if there is data or not :). It's a nice method. No, it is an undefined method. Calling recv() with a buffer length of -1 is undefined behavior, and AFAICS no platform actually defines what should happen with that input. Edited February 6, 2020 by Remy Lebeau Share this post Link to post
Remy Lebeau 1396 Posted February 6, 2020 11 hours ago, Turan Can said: FD_ZERO(FDSet); _FD_SET(SockId, FDSet); Tv.tv_sec := 0; Tv.tv_usec := 0; I := select(0, @FDSet, nil, nil, @Tv); I - I look before the connection. result = 0 sock.. connect.. I - After connecting, I see the result is still the same. result = 0 Because you are merely checking the socket for readability only. If select() returns 0, it timed out, which in this case means the socket is not readable because it has no pending data, not even a graceful disconnect. As long as connect() is successful and the socket doesn't report read/write errors, it is connected. Share this post Link to post
Fr0sT.Brutal 900 Posted February 7, 2020 In brief: to really reliably check whether a socket is alive, you should implement keep-alive (ping-pong) mechanism. OTOH, probably you don't need to know alive status at all, just control result of R/W functions. Share this post Link to post
Turan Can 3 Posted February 7, 2020 This information is great. So how do I do this on android? Is the connection active? How do I know this? is there an example? I get the correct results with "tcp, select". but can you enlighten me with an example of how to do it on android? Share this post Link to post
Turan Can 3 Posted February 7, 2020 Remy, please read my first post and look at the example. I have no problems with Windows socket. My problem is the link on android. Select () gives the same result whether or not there is a link. All my problem is that the select does not give the correct result in andorid. Whether there is a connection or not, the result is 0. Share this post Link to post
Remy Lebeau 1396 Posted February 8, 2020 (edited) 16 hours ago, Turan Can said: So how do I do this on android? Is the connection active? How do I know this? is there an example? I get the correct results with "tcp, select". but can you enlighten me with an example of how to do it on android? What makes you think it is any different for Android? Most platforms use the same Berkeley-based socket API. That is true for Windows. That is true for Posix systems, like Linux (which Android runs on top of). select(), recv(), these functions exist and behave the same on Android (when coding at the native layer, as you describe) as they do on Windows. Edited February 8, 2020 by Remy Lebeau Share this post Link to post