I am trying out simple client-server program using socket programming in c. The program works fine when I execute server first and then client but after two to three successful executions, the client stops connecting to the server. This again starts working if I execute the programs after a certain amount of time.
Client code:
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> int main(){ int clientSocket,len; char buffer[1024]; struct sockaddr_in sadd; clientSocket = socket(PF_INET, SOCK_STREAM, 0); sadd.sin_family = AF_INET; sadd.sin_port = htons(12345); sadd.sin_addr.s_addr = inet_addr("127.0.0.1"); memset(sadd.sin_zero, '', sizeof sadd.sin_zero); len = sizeof sadd; while(connect(clientSocket, (struct sockaddr *) &sadd, len) == -1) { sleep(1); printf("trying again..n"); } read(clientSocket, buffer, sizeof(buffer)); printf("Data received: %s",buffer); return 0; }
Server code:
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> int main(){ int defSock, newSock, len; char buffer[1024]; struct sockaddr_in sadd, cadd; socklen_t addr_size; defSock = socket(PF_INET, SOCK_STREAM, 0); sadd.sin_family = AF_INET; sadd.sin_port = htons(12345); sadd.sin_addr.s_addr = INADDR_ANY; bind(defSock, (struct sockaddr *) &sadd, sizeof(sadd)); if(listen(defSock,5)==0) printf("Listeningn"); else printf("Errorn"); len = sizeof(cadd); newSock = accept(defSock, (struct sockaddr *) &cadd, &len); strcpy(buffer,"Hello Worldn"); int n = write(newSock,buffer,sizeof(buffer)); close(newSock); return 0; }
Executing client in the terminal multiple times:
[kj@localhost Downloads]$ gcc client.c -o client client.c: In function ‘main’: client.c:16:25: warning: implicit declaration of function ‘inet_addr’ [-Wimplicit-function-declaration] sadd.sin_addr.s_addr = inet_addr("127.0.0.1"); ^ client.c:21:3: warning: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration] sleep(1); ^ client.c:25:2: warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration] read(clientSocket, buffer, sizeof(buffer)); ^ [kj@localhost Downloads]$ ./client Data received: Hello World [kj@localhost Downloads]$ ./client trying again.. trying again.. trying again.. trying again.. trying again.. trying again.. trying again.. trying again.. trying again.. ^C [kj@localhost Downloads]$ ./client trying again.. trying again.. trying again.. ^C [kj@localhost Downloads]$ ./client trying again.. trying again.. trying again.. trying again.. ^C [kj@localhost Downloads]$
Simultaneously executing server on another terminal:
[kj@localhost Downloads]$ gcc server.c -o server server.c: In function ‘main’: server.c:31:10: warning: implicit declaration of function ‘write’ [-Wimplicit-function-declaration] int n = write(newSock,buffer,sizeof(buffer)); ^ server.c:33:2: warning: implicit declaration of function ‘close’ [-Wimplicit-function-declaration] close(newSock); ^ [kj@localhost Downloads]$ ./server Listening [kj@localhost Downloads]$ ./server Listening ^C [kj@localhost Downloads]$ ./server Listening ^C [kj@localhost Downloads]$ ./server Listening ^C [kj@localhost Downloads]$
Advertisement
Answer
The use of SO_REUSEADDR
hides another problem:
Your server is only able to serve one client, and does not cleanly close its listening socket when one client has been served.
To correct this, you should add a while
loop in your server in order to allow multiple clients connections.
In your code, I added:
- One
while
loop not to stop after the first client connection, - One test/
perror
to stop the server in case of error, - One
close
on listening socket for a clean exit.
This is the code:
/* include */ int main(){ /* init */ if(listen(defSock,5)==0) printf("Listeningn"); else printf("Errorn"); len = sizeof(cadd); // while they're no error while (1) { // wait for new connection newSock = accept(defSock, (struct sockaddr *) &cadd, &len); // test if client connection succeded if (-1 == newSock) { // something went wrong: kill the server perror("accept()"); break } else { // say hello static const char hello[] = "Hello, world!n"; int n = write(newSock, hello, sizeof hello - 1); /* -1 to exclude the final '' char */ if (n < 0) perror("write"); close(newSock); } } // And close the server listening socket close(defSock); return 0; }