accept() returns error but does not signal remote client to close

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

accept() returns error but does not signal remote client to close

920 Views
timduncan
Contributor I

I'm writing a simple TCP server in MQX 4.0.2.2 using CW 10.5 to run on a TWR-K60F120M.  I create a listening socket, bind it, and call RTCS_selectset().  When that returns, if the selected socket is the listening socket, I try to accept it.  If it's any other socket (which is already connected), I receive data.  After a few successful connections, with data being sent and received successfuly, the sixth socket accepted will fail with accept() returning RTCS_SOCKET_ERROR.  RTCS_geterror(selected_sock) {where selected_sock is the listening socket} returns RTCSERR_OUT_OF_SOCKETS, indicating there is no memory available to accept the new socket.  This is fine, and understandable.  What I don't get, however, is that RTCS never closes the connection with the remote client!  Watching in Wireshark, I see the SYN, SYN/ACK, ACK handshake, followed soon after by the client sending data, because the client thinks the connection is open.  Shouldn't accept() send a FIN or RST flag to the client to terminate or abort the connection upon failure?

Labels (1)
5 Replies

601 Views
timduncan
Contributor I

Chun, yes, the client could eventually detect the situation and close down.  And yes, Martin, it could try to reconnect again later in the hope that another client disconnected in the meantime.  But it would be nice to somehow let the client know the connection failed before it even tries to send data.  Is there a way I could make the RTCS send a FIN or RST to it?  Perhaps call a function to do that?  But without a valid socket handle as Martin pointed out, that is not possible.  An idea just occurred to me - I know what _RTCS_socket_part_max or RTCSCFG_SOCKET_PART_MAX is set to (It's when that limit is reached that accept() fails with RTCSERR_OUT_OF_SOCKETS).  So just before I reach that limit, I could shut down my listening socket.  That way, remote clients would be unable to connect until one or more sockets close and I start listening again.  But there's something about doing this that just doesn't "feel right."  I can't put my finger on it.  How does any one else handle this?  Should I simply rely on the client to close when it gets no response after sending?

601 Views
Martin_
NXP Employee
NXP Employee

There is possibility that some clients disconnect or sockets are shutdown by application. So a socket will become available for RTCS, then server can call accept() again.

The server task, in case accept() returns error, just calls accept() again. You can add some _time_delay() before next accept(). See for example HTTPSRV.

0 Kudos

601 Views
susansu
NXP Employee
NXP Employee

Hi Tim,

                By default, there is a limit for the maximum number of sockets you can create in MQX, which is defined in rtcscfg.h by the macro RTCSCFG_SOCKET_PART_INIT and the default value is 6. You can change it to a larger value for the application requirements.

                About the second question, when server detect socket error, server could call shutdown() to close the socket, then client will know that.

0 Kudos

601 Views
Martin_
NXP Employee
NXP Employee

Chun, but the actual problem with shutdown() in this case is that you don't have the child socket handle, which would be the parameter for such a shutdown().

Currently the client socket should timeout, as the server won't acknowledge any data.

For number of sockets, I use _RTCS_socket* global variables, so I can increase the number of sockets my application can create, example:

_RTCS_socket_part_init = 4;

_RTCS_socket_part_grow = 2;

_RTCS_socket_part_max  = 20;

601 Views
susansu
NXP Employee
NXP Employee

Hi Martin,

                Yes you are right. I forgot that if accept error, the accept function will not return the handle of the socket but return RTCS_SOCKET_ERR.

                When socket number exceeds the limit, accept function will not generate new socket struct for the new connection, without closing or resetting the connection so the client still takes the connection established and keep sending packets. Since the server will not respond to those packets, the client could do something to know this situation.

            PS: Sorry Tim, not the RTCSCFG_SOCKET_PART_INIT , but the RTCSCFG_SOCKET_PART_MAX limit the maximum number of sockets and it's default value is RTCSCFG_SOCKET_PART_INIT(default 6)