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
whileloop not to stop after the first client connection, - One test/
perrorto stop the server in case of error, - One
closeon 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;
}