Reputation: 1565
Right now, I am trying to specify options with setsockopt()
using the following code:
// bind socket
// Use setsockopt() function to make sure the port is not in use
int yes = 1;
setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
setsockopt(TCPSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
status = bind(TCPSocket, host_info_list->ai_addr, host_info_list->ai_addrlen);
if (status == -1) std::cout << "bind error" << std::endl ;
// listen for connections
status = listen(TCPSocket, 5);
if (status == -1) std::cout << "listen error" << std::endl ;
int new_sd;
struct sockaddr_storage their_addr;
socklen_t addr_size = sizeof(their_addr);
new_sd = accept(TCPSocket, (struct sockaddr *)&their_addr, &addr_size);
if (new_sd == -1) std::cout << "listen error" << std::endl ;
Note tv
is an already-specified timeval.
When I make only the first setsockopt()
call, everything works fine. However, with the addition of the second (which does not return any errors), I encounter the second "listen error" specified in the code. I'm not sure why setting the timeout value affect this, can someone explain?
I do not take credit for the code specified; it is modified from the code presented in the tutorial here: http://codebase.eu/tutorial/linux-socket-programming-c/
Upvotes: 0
Views: 2089
Reputation: 1565
Joachim's solution did a great job of answering my intial question and explaining setsockopt(). To answer my own question after realizing the issue was further down in the code, the timeout affects the server being able to listen to a port. Say the timeout is only 10ms, the server must be started, then the client, and a connection must be established in that time. This wasn't happening in my case, thus the resulting error.
Upvotes: 0
Reputation: 409176
If you see a TCP state diagram like this one you see there's a state called TIME_WAIT
when actively closing a socket. This state can take some time before it ends, up to four minutes according to RFC793.
While the socket is in the TIME_WAIT
you can not bind to an interface using the same address-port pair as the socket that is in the wait state. Setting the SO_REUSEADDR
flag om a socket enables other sockets to bind to the address when the current socket (with the flag set) is in the TIME_WAIT
state.
The SO_REUSEADDR
option is most useful for server (passive, listening) sockets.
As for your problem, after each call to setsockopt
check what it returns, and if it's -1
then you check errno
to see what went wrong. You can use perror
or strerror
to print or get a printable string for the error, like
if (setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0)
{
std::cerr << "Error setting the SO_REUSEADDR: " << strerror(errno) << '\n';
// Do something appropriate
}
Upvotes: 2