I'm creating a server/client, but I have a problem. If I boot the server and the client for the first time, everything works fine. Then I close them, I boot them again in few seconds, and I receive a "connection refused" error in the client. I always boot the server first, and the client after. Here's the code.
DoLogin
is an easy function with 2 read and 2 write. What's wrong in this code?
server.c
int main(){
int ds_sock;
struct sockaddr_in my_addr;
ds_sock=socket(AF_INET,SOCK_STREAM,0);
memset(&my_addr,0,sizeof(my_addr));
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(25000);
my_addr.sin_addr.s_addr=INADDR_ANY;
if(bind(ds_sock,(struct sockaddr *)&my_addr,sizeof(my_addr))<0){
printf("Error in bind");
}
listen(ds_sock,2);
int ds_sock_acc;
struct sockaddr_in addr;
size_t sin_size = sizeof(struct sockaddr_in);
if((ds_sock_acc=accept(ds_sock,(struct sockaddr *)&addr,&sin_size))<1){
printf("Error accept");
}
printf("Connected\n");
char *usr = DoLogin(ds_sock_acc);
printf("%s is connected\n",usr);
close(ds_sock_acc);
close(ds_sock);
return 0;
}
client.c
int main(){
int ds_sock;
ds_sock = socket(AF_INET, SOCK_STREAM,0);
int ret;
struct sockaddr_in Eaddr;
Eaddr.sin_family = AF_INET;
Eaddr.sin_port = htons(25000);
Eaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
ret = connect(ds_sock,(struct sockaddr *)&Eaddr,sizeof(Eaddr));
if(ret==-1){
printf("Error connect");
perror("error:");
exit(EXIT_FAILURE);
}
printf("Connect OK\n");
char *usr = DoLogin(ds_sock);
printf("Logged in as %s\n",usr);
close(ds_sock);
return 0;
}
The O/S usually prevents a listening socket from being recreated on the same port for a while after the previous socket has closed, to prevent messages originally destined for the original socket being delivered to the new one.
To override this behaviour you need setsockopt
with the SO_REUSEADDR
option (on the server side):
int optval = 1;
setsockopt(ds_sock, SO_REUSEADDR, &optval, sizeof(optval));
[error checking omitted]