Reputation: 2843
I have the following example code for using Linux sockets:
void serve_request(int newsockfd)
{
char buffer[256];
int n;
/*if connection established then start communicating*/
bzero(buffer, 256);
n=read(newsockfd, buffer, 255);
if(n<0)
{
perror("Error reading from socket");
}
printf("Here is the message: %s\n",buffer);
/*write response to the client*/
n=write(newsockfd,"I got your message", 18);
if(n<0)
{
perror("Error writing to socket");
exit(1);
}
//close(newsockfd);
}
int main(int argc, char* argv)
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
/*first call to socket function*/
sockfd=socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0);
if(sockfd<0)
{
perror("Error opening socket");
exit(1);
}
/*initialize socket structure*/
bzero((char*)&serv_addr, sizeof(serv_addr));
portno=5001;
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=INADDR_ANY;
serv_addr.sin_port=htons(portno);
/*now bind the host address using bind() call.*/
if(bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr))<0)
{
perror("Error on binding");
exit(1);
}
/*now start listening for the clients, here process will
go in sleep mode and will wait for the incoming connection*/
listen(sockfd, 5);
clilen=sizeof(cli_addr);
while(1)
{
/*accept actual connection from the client*/
newsockfd=accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
if(newsockfd<0)
{
perror("Error on accept");
exit(1);
}
serve_request(newsockfd);
}
return 0;
}
Everything works fine with this. When I execute ./a.out
it starts the socket server and waits for clients. When I exit the code using ^C
it stops and returns to prompt.
However, if the code was complied with the last line (//close(newsockfd);
) in method void serve_request(int newsockfd)
uncommented and a client had come and gone, then on pressing ^C
and invoking the server again with ./a.out
, it shows Error on binding: Already in use
.
But if I have compiled the code with the last line commented, then it works fine, meaning I can immediately invoke the server with ./a.out
and have the server up again without waiting for some time as in the previous case.
Can somebody throw some light on properly handling this. Any help is much appreciated. Thank you.
Upvotes: 1
Views: 1520
Reputation: 2030
Your problem has little to do with the close(). I suspect you just waited different amounts of time between invocations.
1) You are calling setsockopt wrong, so the option you are trying to set has no effect. This is an example of a working invocation:
int optval = 1; //enable option
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
perror("setsockopt()");
exit(1);
}
Note that the third argument is a pointer and non-optional for any sensible invocation. man setsockopt:
Most socket-level options utilize an int argument for optval. For setsockopt(), the argument should be nonzero to enable a boolean option, or zero if the option is to be disabled.
2) You did not check return value of setsockopt()
so there was little hope of locating the error.
3) Do close the newsockfd
, when you are done with it. Also close sockfd
before exiting the program.
Summary: Always check return values of all system calls. Be prepared for all return values listed on the man-page. Free/close all allocated resources in all paths of execution.
ps. To be a little snarky, all the #include
statements required to compile the code are part of a proper question.
Upvotes: 1
Reputation: 29744
You should set SO_REUSEADDR. You did it - but incorrectly. This is how to do it properly:
/* SO_REUSEADDR allows a new server to be started
* on the same port as an existing server that is
* bound to the wildcard address, as long as each
* instance binds a different local IP address.
* This is common for a site hosting multiple HTTP
* servers using the IP alias technique */
int reuseaddr_on = 1;
if( setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR,
&reuseaddr_on, sizeof( reuseaddr_on)) < 0)
{
// log
}
Remember to set SO_REUSEADDR option before a call to bind()
.
Upvotes: 0
Reputation: 40145
When you opened the socket, you allocated an operating system resource and told the o/s taht you want to reuse the socket address.
There is no automatic cleanup when your program ends. The resource remains allocated.
Uncomment that close()
and get into the habit of always freeing any and all resources,whether memory, sockets, mutexes or whatever.
Upvotes: 3