Reputation: 31
I want to build a very simple server that accepts only one connection at a time on an embedded device (running an RTOS).
Two option comes to my mind concerning the socket listener:
*** A: Reset listener only when listener has an error ***
int fd_Listener = listen(INADDR_ANY, listenPort, 1);
while(fd_Listener){ // while listner is alive
int fd_Socket = accept(); //Blocking
while(fd_socket){ //while socket is alive and no error occurred
//read() write() process() etc ...
}
}
*** B: Reset listener every time I reset the socket (for each new connection a new listener) ***
while(1){
int fd_Listener = listen(INADDR_ANY, listenPort, 1);
int fd_Socket = accept(); //Blocking
while(fd_socket){ //while socket is alive and no error occurred
//read() write() process() etc ...
}
}
Any idea what is considered a good practice? Which implementation is more prone to error or bugs?
Upvotes: 2
Views: 100
Reputation: 181199
Any idea what is considered a good practice? Which implementation is more prone to error or bugs?
You seem to have several misconceptions here. Be aware that:
calling listen()
sets up the specified socket as a listening socket. This is a persistent state -- it does not need to be refreshed as long as the socket remains open. The best you can hope for from calling it again on a socket that is already listening is that doing so does not mess you up. There is no reason to expect that it will "reset" an already listening socket, nor is it even clear in what sense you think any kind of reset might be needed.
the return value of listen()
is an ordinary number, not a file descriptor or any other kind of handle on another resource. You can use it to determine whether the listen()
call that returned it succeeded, but it does not report on the state of the socket at any time thereafter. If an issue arose with the socket itself after it successfully started listening (very unlikely) then you would learn about it via the return values of accept()
calls on that socket.
accept()
returns -1 to indicate an error, which evaluates to true in boolean context. 0 is a valid file descriptor number that might, under some circumstances, be returned by accept()
. On success, this is a handle on another resource (a connected socket), but the value of the variable in which you store it does not automagically change in response to the state of that socket. You would detect unexpected issues with that socket, including closure, via the return values of I/O functions (read()
, write()
, etc.) operating on that socket.
if accept()
fails then immediately trying again is unlikely to get a different result under most circumstances. Immediately after the failure, the errno
variable will contain a code that describes the nature of the error. If you want to do anything in the event of failure other than simply terminating the program then that should probably be informed by the nature of the error.
The natural idiom for operating a socket-based service is:
socket()
, bind()
, and listen()
.accept()
as many connections from it as you wish. Service these as appropriate and close()
each when you are done with it.close()
the socket before the program terminates.Upvotes: 1
Reputation: 125
I would say that option A is a better solution because it is more efficient as it doesn't repeatedly create and destroy socket resources, reduces system calls and overhead. Creating new sockets frequently (option B) can lead to resource leaks if proper cleanup isn't performed, which can be pain in the *ss to fix if things go wrong.
Furthermore, with option B you might encounter "Address already in use" errors if the previous socket wasn't properly cleaned up. So I would stay away from option B.
Upvotes: 1