C socket TCP server fails after client disconnects - c

I am modifying the server code from here http://www.linuxhowtos.org/C_C++/socket.htm. I want to reset the server when the client disconnects, so it's ready the next time for the client. But instead when I close the client side, the server shuts down and nothing is written in the server log. Since I only want to handle one client at a time, I don't need to fork right? Otherwise the server works fine and responds to messages I've sent from a client I wrote in C#.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
FILE *fp;
double square(double x)
{
return x*x;
}
void error(const char *msg)
{
fprintf(fp, "%s", msg);
fprintf(fp, "%s", "\n");
}
int main(int argc, char *argv[])
{
fp = fopen("serverlog.txt", "a");
int sockfd;
int newsockfd;
int portno = 43635;
int clientIsConnected;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
while (1)
{
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
error("ERROR opening socket");
close(sockfd);
return 0;
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
error("ERROR on binding");
close(sockfd);
return 0;
}
if (listen(sockfd,5) < 0)
{
error("ERROR on listen");
close(sockfd);
return 0;
}
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
error("ERROR on accept");
close(newsockfd);
close(sockfd);
return 0;
}
clientIsConnected = 1;
while (clientIsConnected)
{
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if (n < 0)
{
error("ERROR reading from socket");
clientIsConnected = 0;
break;
}
double x = atof(buffer);
double squared = square(x);
char response[256];
sprintf(response, "%f", squared);
n = write(newsockfd, response, strlen(response));
if (n < 0)
{
error("ERROR writing to socket");
clientIsConnected = 0;
break;
}
}
}
close(sockfd);
return 0;
}

It may be that your server stops because it received SIGPIPE. You can use
signal(SIGPIPE, SIG_IGN);
to keep your program going and you can handle the closed communication in your application code.

Related

Issue using c sockets with threads to read from and write to the socket

I want to write a TCP server-client chat, but when I start the two threads for reading from and writing to a socket at both sides, I think they block each other out. Can anyone help me with this?
Server Code:
/* A simple server in the internet domain using TCP the port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
struct server_args_runner{
char buffer [256];
int newsockfd;
pthread_t tid;
pthread_attr_t attr;
//read/write attribute (read == 0 and write == 1)
int rw;
};
void error(char *msg){
perror(msg);
exit(1);
}
void* server_runner_fun(void* args){
// this is the chat part!
// get args:
int n;
struct server_args_runner *sar = (struct server_args_runner*) args;
if(sar->rw == 0){
printf("server thread trys to read from socket...\n");
//read-part
while(1){
bzero(sar->buffer, 256);
n = read(sar->newsockfd, sar->buffer, 255);
if (n < 0){
error("ERROR reading from socket");
}
}
printf("%s\n", sar->buffer);
} else {
printf("server thread trys to write to socket...\n");
//write-part
while(1){
bzero(sar->buffer, 256);
fgets(sar->buffer, 255, stdin);
n = write(sar->newsockfd, sar->buffer, strlen((char *) &(sar->buffer)));
if (n < 0){
error("ERROR writing to socket");
}
}
}
}
int main(int argc, char *argv[]){
//fd = filedescriptor
int sockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2){
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
//socket(...) returns a descriptor
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1){
error("ERROR opening socket");
}
printf("Socket created successfully.\n");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
//htons(..) converts the short from hostbyteorder to networkbyteorder
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) == -1){
error("ERROR on binding");
}
printf("binding successfull on port %d\n", portno);
listen(sockfd, 2);
clilen = sizeof(cli_addr);
printf("server is listening ...\n");
struct server_args_runner server_write_t, server_read_t;
server_write_t.newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
printf("server accepted connection to client.\n");
if (server_write_t.newsockfd < 0){
error("ERROR on accept");
}
//initializing both server_threads
pthread_attr_init(&server_write_t.attr);
pthread_attr_init(&server_read_t.attr);
server_write_t.rw = 1;
server_read_t.rw = 0;
bcopy(&server_write_t.newsockfd, &server_read_t.newsockfd, sizeof(server_write_t.newsockfd));
pthread_create(&server_write_t.tid, &server_write_t.attr, server_runner_fun, &server_write_t);
pthread_create(&server_read_t.tid, &server_read_t.attr, server_runner_fun, &server_read_t);
pthread_join(server_write_t.tid, NULL);
pthread_join(server_read_t.tid, NULL);
return 0;
}
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
struct client_args_runner{
char buffer [256];
int sockfd;
pthread_t tid;
pthread_attr_t attr;
//read/write attribute (read == 0 and write == 1)
int rw;
};
void error(char *msg){
perror(msg);
exit(0);
}
void* client_runner_fun(void* args){
// this is the chat part!
// get args:
int n;
struct client_args_runner *car = (struct client_args_runner*) args;
if(car->rw == 0){
printf("client thread trys to read from socket...\n");
//read-part
while(1){
bzero(car->buffer, 256);
n = read(car->sockfd, car->buffer, 255);
if (n < 0){
error("ERROR reading from socket");
}
}
printf("%s\n", car->buffer);
} else {
printf("client thread trys to write to socket...\n");
//write-part
while(1){
bzero(car->buffer, 256);
fgets(car->buffer, 255, stdin);
n = write(car->sockfd, car->buffer, strlen((char *) &(car->buffer)));
if (n < 0){
error("ERROR writing to socket");
}
}
}
}
int main(int argc, char *argv[]){
int portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
if (argc < 3){
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
struct client_args_runner client_write_t, client_read_t;
client_write_t.sockfd = socket(AF_INET, SOCK_STREAM, 0);
bcopy(&client_write_t.sockfd, &client_read_t.sockfd,
sizeof(client_write_t.sockfd));
if (client_write_t.sockfd == -1){
error("ERROR on creating socket_file_descriptor");
}
printf("socket created successfully.\n");
server = gethostbyname(argv[1]);
printf("hostname is valid.\n");
if(server == NULL){
fprintf(stderr, "Error, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
printf("before connecting to client..\n");
if (connect(client_write_t.sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) == -1){
error("ERROR connecting");
}
printf("client connected successfully to server.\n");
//initializing both client_threads
pthread_attr_init(&client_write_t.attr);
pthread_attr_init(&client_read_t.attr);
client_write_t.rw = 1;
client_read_t.rw = 0;
pthread_create(&client_write_t.tid, &client_write_t.attr, client_runner_fun, &client_write_t);
pthread_create(&client_read_t.tid, &client_read_t.attr, client_runner_fun, &client_read_t);
pthread_join(client_write_t.tid, NULL);
pthread_join(client_read_t.tid, NULL);
return 0;
}
Your printfs in both the client and server readers are outside the while(1) loops, so your client and server are communicating fine, you just aren't printing anything you read from the sockets.

Client hangs when tries to read back from server tcp

i am trying to create a simple tcp server-client. My programm works fine if client sends data to server but when server tries to answer back the whole connection hangs. I am using write()/read() functions .
Server code :
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <stdbool.h>
#define SIZE 700000000
///////////////////////////////////////////////////////////////////////////
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);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
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);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
listen(sockfd, 10);
clilen = sizeof(cli_addr);
/* Accept actual connection from the client */
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
bzero(buffer, 255);
int readbyte = 0;
do {
readbyte = read(newsockfd, buffer, 1024);
if (readbyte < 0)
{
perror("ERROR on reading socket!");
break;
}
if (readbyte > 0)
{
//printf("Here is the message: %s\n",buffer);
}
} while (readbyte > 0); /* until EOF */
int writen = write(newsockfd, "I received your message", strlen("I received your message") + 1);
if (writen<0){
perror("Error");
}
//debug();
return 0;
}
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
//////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int mode;
char *code;
char buffer[256];
char *uptr = buffer;
int i;
if (argc < 3) {
fprintf(stderr, "Use: %s [hostname] [port] [args]\n", argv[1]);
exit(0);
}
portno = atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
int sock_et = connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr);
/* Now connect to the server */
if (sock_et < 0) {
perror("ERROR connecting");
exit(1);
}
/* some code... */
while (len > 0) {
int writen = write(sockfd, buf, len + 1);
if (writen < 0)
{
printf("Error writting to socket!\n");
break;
}
len -= writen;
buf += writen; /* tricky pointer arythmetic */
}
printf("Finished writing to server\n");
bzero(buffer, 256);
int readbyte;
do {
readbyte = read(sock_et, buffer, 1024);
if (readbyte < 0)
{
perror("ERROR on reading socket!");
break;
}
if (readbyte > 0)
{
//printf("Here is the message: %s\n",buffer);
}
} while (readbyte > 0); /* until EOF */
printf("%s\n",buffer );
close(sockfd);
return 0;
}
Any help would be appreciated! Thanks!
Your client code doesn't compile
You are never going to get a 0 (EOF) from read while the socket is open (in either the client or server) -- so just add a break after a successful read for now.
You are not closing the socket in the server
In the client, you need to read from sockfd, not sock_et
There are probably other issues. It looks like you are trying to use client.c/server.c from here: http://www.linuxhowtos.org/C_C++/socket.htm
If I use those files, it works fine. So start over from them and apply your changes more carefully.

How to make the server keep responding to requests until its process is killed by typing ctrl-c

server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
char *result1 = "Ian G. Harris";
char *result2 = "Joe Smith";
char *result3 = "Jane Smith";
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
printf("Address server started\n");
while (strcmp(buffer, "+++\n") != 0)
{
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) error("ERROR reading from socket");
if (strcmp(buffer, "harris#ics.uci.edu\n") == 0)
{
printf("%s\n", result1);
n = write(newsockfd,"harris#ics.uci.edu",18);
if (n < 0) error("ERROR writing to socket");
}
else if(strcmp(buffer, "joe#cnn.com\n") == 0)
{
printf("%s\n", result2);
n = write(newsockfd,"joe#cnn.com",18);
if (n < 0) error("ERROR writing to socket");
}
else if(strcmp(buffer, "jane#slashdot.org\n")==0)
{
printf("%s\n", result3);
n = write(newsockfd,"jane#slashdot.org",18);
if (n < 0) error("ERROR writing to socket");
}
}
return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
while (strcmp(buffer, "+++\n") != 0)
{
printf("> ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
if (strcmp(buffer, "+++\n") == 0)
{
exit(0);
}
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
}
return 0;
}
I wrote a server.c and a client.c and I need to make some changes to my server.c so that it never quits until I press ctrl-c. I put the client part just in case.
below is the correct format:
client
> harris#ics.uci.edu
Ian G. Harris
> joe#cnn.com
Joe Smith
>
server
Address server started
harris#ics.uci.edu
joe#cnn.com
the only problem I have here is that when I type "+++" in the client, both the client and server quit. The client should quit but the server should wait for another client and continue responding to requests and printing the associated email addresses until its process is killed externally by typing ctrl-c.
Can someone tell me how to fix it? specific examples would be better. Thanks in advance.
Try loop with accept:
while(true)
{
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
printf("Accepted new connection\n");
while (strcmp(buffer, "+++\n") != 0) { ... }
}
Please note that this cannot handle simultaneous connections, you need to use asynchronous IO for that which is more complex.

Multiple connections to server via socket in C

Basically my program is suppose to be able to have multiple connections to a server at the same time. Which I have running, except when they have to send large amounts of text via a socket, then it is unpredictable. Sometimes it works, sometimes not. The plaintext4 file is 69,333 bytes long, when I try to send it 5 times at the same time over the network via a socket to a server and back, it doesn't work always; sometimes it works, sometimes parts of it is missing, etc. When I used basically the same thing using write and read it worked, but when I tried to the same with large amounts of text, it didn't work almost at all, hence why I switched to send and recv. Now I can't figure out how to make it so when someone is sending sometime, no one else will send at the same time... because I think that is the problem I am having. Any help would great.
The status of my program right now:
- Works when sending small amounts of text.
- Doesn't work when sending large amounts of text.
- The size of the file that it creates when it doesn't work can vary, sometimes is above 60K bytes sometimes as little as 20K bytes. Meaning that probably one of the other processes wrote to the socket or read from it before the correct process got to receive it. (I think).
server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
const int BUFF_SIZE = 70000;
int sockfd, newsockfd, portno, newsockfdc;
socklen_t clilen;
char buffer[BUFF_SIZE];
pid_t pid;
int status;
char temp[BUFF_SIZE];
struct sockaddr_in serv_addr, cli_addr;
int n;
int i;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
while(1){
waitpid(-1, &status, WNOHANG);
memset(buffer, '\0', sizeof(buffer));
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
if((pid=fork())==0)
{
close(sockfd);
int d;
for(i=0; i<1; i++)
{
bzero(buffer,BUFF_SIZE);
//sleep(1);
d=BUFF_SIZE-1;
//n = read(newsockfd,buffer,d);
n = recv(newsockfd, buffer, sizeof(buffer), 0);
if (n < 0) error("ERROR reading from socket");
bzero(temp, BUFF_SIZE);
strcpy(temp, buffer);
n = send(newsockfd, buffer, strlen(buffer)+1, 0);
//n = write(newsockfd,temp,sizeof(temp));
if (n < 0) error("ERROR writing to socket");
}
close(newsockfd);
exit(0);
}
else{
waitpid(-1, &status, WNOHANG);
close(newsockfd);
}
}
close(sockfd);
return 0;
}
client code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
const int BUFF_SIZE = 70000;
char buffer[BUFF_SIZE];
if (argc < 4) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
int numt;
numt = atoi(argv[3]);
char numc[5];
bzero(numc, 5);
sprintf(numc, "%d", numt);
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
bzero(buffer,BUFF_SIZE);
FILE *fp;
size_t bytes_read;
if((fp=fopen("./plaintext4", "r+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
sleep(1);
n=send(sockfd, buffer, strlen(buffer)+1, 0);
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,BUFF_SIZE);
n=BUFF_SIZE - 1;
n = recv(sockfd, buffer, sizeof(buffer), 0);
if (n < 0)
error("ERROR reading from socket");
char filei[90];
bzero(filei,90);
strcpy(filei, "plaintext");
strcat(filei, numc);
strcat(filei, "_a");
if((fp=fopen(filei, "w+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
fclose(fp);
close(sockfd);
return 0;
//sleep(1);
printf("Sending message 1: plaintext1\n");
bzero(buffer,BUFF_SIZE);
if((fp=fopen("./plaintext1", "r+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fread(buffer, sizeof(buffer), 1, fp);
fclose(fp);
n = send(sockfd, buffer, strlen(buffer)+1, 0);
//n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error ("ERROR writing to socket client side");
bzero(buffer, BUFF_SIZE);
n=BUFF_SIZE - 1;
n = recv(sockfd, buffer, sizeof(buffer), 0);
//n = read(sockfd, buffer, n);
if (n < 0)
error("ERROR reading from socket client side");
printf("message: %s\n", buffer);
strcat(filei, "b");
if((fp=fopen(filei, "w+"))==NULL)
{
perror("fopen(2) file error");
exit(EXIT_FAILURE);
}
bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
fclose(fp);
close(sockfd);
return 0;
}
You server process can (which process accept() call) can be blocked by waitpid - it is can be cause of your problem.
Alternatively you can implement waitpid call via SIGCHLD signal handler and remove waitpid from main().
Best regards!

c - client server communication via socket in infinite loop

I have the following code below for a client page and a server page, for which I want to send five messages from the client side to the server side (for this initial test, anyway). The code works fine if I don't put it in a loop, but then I can only send one message before both the client and server close. When I put the code in a loop, it seems to get stuck in some sort of deadlock. The results I get are below followed by the code. I've tried various changes and done extensive research but just can't make it work. Thanks in advance for any solutions offered.
Server side results
./server 5000
Here is the message: test
Client side results
./client localhost 5000
Please enter the message: test
I got your message
Please enter the message: another test
Please enter the message: test again
Please enter the message: test yet again
// The server stops acknowledging receipt of the message and I have to keep resetting both client and server
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
printf("Need at least two arguments\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
printf("ERROR opening socket\n");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
printf("ERROR on binding\n");
listen(sockfd,atoi(argv[1]));
clilen = sizeof(cli_addr);
while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
if (newsockfd < 0)
printf("ERROR on accept\n");
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0) printf("ERROR reading from socket\n");
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message\n",18);
if (n < 0) printf("ERROR writing to socket\ns");
}
close(sockfd);
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
printf("Not enough arguments\n");
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
printf("Error opening socket\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
printf("Error: no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
printf("Error connecting\n");
int i = 0;
while (i < 5) {
printf("Please enter the message: ");
bzero(buffer, 256);
fgets(buffer, 255, stdin);
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
printf("Error writing to socket");
bzero(buffer, 256);
n = read(sockfd, buffer, 255);
if (n < 0)
printf("Error reading from socket");
printf("%s\n", buffer);
i++;
}
close(sockfd);
return 0;
}
You need to restructure your code to deal with the one connection you have before accepting another one. This is terrible code but is the basic template for what you want to do. Even so you can't deal with more than one connection at a time with this. You either have to multiplex or thread. Also, always read/write in a loop because you are not guaranteed to get a full request filled on any one call. Learn about and use perror or brothers.
void do_stuff(int sock)
{
for (int i = 0; i < 5; ++i)
{
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if (n < 0)
printf("ERROR reading from socket\n");
printf("Here is the message: %s\n", buffer);
n = write(newsockfd, "I got your message\n", 18);
if (n < 0)
printf("ERROR writing to socket\ns");
}
}
while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0)
{
if (newsockfd < 0)
printf("ERROR on accept\n");
do_stuff(newsockfd);
close(newsockfd);
}
I know its too late. But for someone who might have the same doubt I am trying to answer this.
Answer
How about changing the server program to this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
printf("Need at least two arguments\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
printf("ERROR opening socket\n");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
printf("ERROR on binding\n");
listen(sockfd,atoi(argv[1]));
clilen = sizeof(cli_addr);
while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
if (newsockfd < 0)
printf("ERROR on accept\n");
bzero(buffer,256);
while(true)
{
n = read(newsockfd,buffer,255);
if (n < 0)
{
printf("ERROR reading from socket\n");
break;
}
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message\n",18);
if (n < 0)
{
printf("ERROR writing to socket\ns");
break;
}
}
close(newsockfd);
}
close(sockfd);
return 0;
}
This is the changed part. I changed the code slightly such that the connection will close if any write or read error occurs.
while ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) >= 0) {
if (newsockfd < 0)
printf("ERROR on accept\n");
bzero(buffer,256);
while(true)
{
n = read(newsockfd,buffer,255);
if (n < 0)
{
printf("ERROR reading from socket\n");
break;
}
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message\n",18);
if (n < 0)
{
printf("ERROR writing to socket\ns");
break;
}
}
close(newsockfd);
}

Resources