Hello everyone.
I'm wirting an application for an LPC Controller using Keil/Arm MDK and BSD Sockets.
In the application I close a TCP listen socket and want to reopen it a short time later. I get an Error trying after closing it and trying to bind the newly created Socket: BSD_EADDRINUSE (-17). Seems to indicate that it is in something of a TIME_WAIT state, so I can't reuse that port until the set time passed.
This would be perfectly fine for a connection socket. But for a listen socket, I don't see the point. After closing it no connection would be accepted any more anyway. setsockopt() exists but SO_REUSEADDR is not implemented by the MDK. So how would I try to work around this?
Thanks for any help.
please check the manual page of the API netTCP_Close()
https://www.keil.com/pack/doc/mw/Network/html/group__tcp__user__api.html#gad3b70b023f209cd7687f15f553219185
"When a socket is used in the netTCP_Listen functions, the socket does not close by calling netTCP_Close. Only the active connection is closed, and the socket will be available for new incoming connection. To close such a socket, the function netTCP_Close needs to be called twice."
Also keep in mind a TCP socket is a "hand-shake" based state of machine:
http://www.tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
any change of socket states requires acknowledgement from both sides, which takes time.
Hello Chen,
it's been a while. (Support cases.)
Well, as I wrote, I'm using the BSD sockets interface. According to the code under www.keil.com/.../group__using__network__sockets__bsd__func.html I get a new socket descriptor when calling accept() (the connection socket). The listen socket apparently is still there and can be (and is in the example) closed without interfering with the actual connection.
I know the BSD socket API runs on top of TCP and UDP APIs. So is the listen socket (BSD API) not actually closed because the underlying TCP socket API socket doesn't support this? (To me that would implement that calling close() only results in the second close() to the TCP socket API socket to be called automagically right after the connection is closed().) Because in my case the connection is still active when I try to close the listen socket and then try to bind a new one to the same port as the before.
If that is the case then with the MDK implementation what I'm trying to do is impossible as is the implementation of SO_REUSEADDR functionality.
Is that it? (In that case some more explanation about this in the documentation might come in handy.)
sorry that I didn't notice you were asking BSD socket, instead of native TCP socket.
The error "BSD_EADDRINUSE" happens, when the local socket with a specific port is currently being used, which cannot be reused.
If you read through the example code you referred to above, you will see closing the "parent socket" is not meant for you to reuse the socket bound to the same address and port.
actually, what I tried to do is establish several TCP connections with my device being the server. (Closing and re-opening the socket was an attempted workaround.) With a BSD socket, this doesn't work. The listen socket queues incoming connection requests while a connection is active but I can't establish a second connection by calling accept() until the first connection is closed. (Conforming to https://www.keil.com/pack/doc/mw/Network/html/group__using__network__sockets__bsd__func.html#ga18e88467cfdbc3c361d53b9f928a87ab)
In https://www.keil.com/pack/doc/mw6/Network/html/using_network_sockets_tcp.html it says "The Network Component can handle multiple connections on the same port." and further down the page "Server applications often require to be able to accept several TCP connections from clients on the same port. The handling of these multiple connections must be implemented in the user application." This document is for Version 6 of the Network Component. I couldn't find anything similar for Version 7.
Is it still possible to have multiple connections via one listening socket opened at the same time using the TCP Socket API in Version 7 of the Network Component?
Kind Regards.
Then you should consider using native TCP socket APIs instead of BSD socket
Please install and check the CMSIS-Driver_Validation pack and see SockServer.c in the .\Tools\SockServer\Embedded\MDK\Source folder.
This server performs several services (ECHO, DISCARD, CHARGEN, ..) using BSD sockets. The StreamServer thread is waiting for any connection using the select() function. StreamServer then accepts the connection and creates a new thread that manages the connection until it is closed. The current configuration can accept 5 simultaneous connections: two for ECHO, two for CHARGEN and one for the DISCARD service.
I believe this is what you are looking for.
Solved! Finally.
The BSD Sockets API was working all the time. I just had to understand that after accepting a connection request it was NOT instantly removed from the queue that wast started with listen(<socket>, <queue size>);. So to have two connections simultaneously, 1 didn't do.
I'll mark Franc's answer as the accepted one since that led me to realize my error.
Thank both of you very much.