I'm trying to implement a multithreaded C server-client as implemented here
I want to work with an infinite loop to read/send messages as much as I want, until let's say the client sends SIGINT or SIGSTOP signal or writes the message "stop". So far only the first message that the client sends is received by the server, and for this the server responds with "abcd" as shown in code. Starting with the 2nd message, I can't see the server replies in the client anymore, and like from the 3rd message, the client just exits, like the connection is ended. Meanwhile, the server is still running. I will put my code below, I don't think I am working correctly with write/read.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/syscall.h> //thread_id
#define PORT 7507
#define BUFFER_SIZE 2048
#define BACKLOG 10
#define gettid() ((pid_t)syscall(SYS_gettid))
typedef struct pthread_args {
int sockfd;
struct sockaddr_in client_address;
clock_t start, stop;
char* message;
float seconds;
float delay;
} pthread_args;
void* handler(void* args) {
pthread_args* pthread_arg = (pthread_args*)args;
int sockfd = pthread_arg->sockfd;
struct sockaddr_in client_address = pthread_arg->client_address;
float seconds = pthread_arg->seconds;
float delay = pthread_arg->delay;
char* message = pthread_arg->message;
free(args);
printf("Message received from client (thread id=%d): %s\n", gettid(), pthread_arg->message);
if((write(sockfd, "abcd", 4))<0) {
perror("write");
exit(EXIT_FAILURE);
}
close(sockfd);
return NULL;
}
int main() {
int sockfd, new_sockfd, bytes;
char buffer[BUFFER_SIZE];
struct sockaddr_in server_address;
pthread_attr_t pthread_attr;
pthread_args* pthread_arg;
pthread_t thread;
socklen_t client_len;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
server_address.sin_addr.s_addr = INADDR_ANY;
//socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
//bind
if (bind(sockfd, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
//listen
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
if (pthread_attr_init(&pthread_attr) != 0) {
perror("pthread_attr_init");
exit(EXIT_FAILURE);
}
if (pthread_attr_setdetachstate(&pthread_attr, PTHREAD_CREATE_DETACHED) != 0) {
perror("pthread_attr_setdetachstate");
exit(EXIT_FAILURE);
}
while(1) {
pthread_arg = (pthread_args*)malloc(1*sizeof(pthread_args*));
if(!pthread_arg) {
perror("malloc");
exit(EXIT_FAILURE);
}
//accept
client_len = sizeof(pthread_arg->client_address);
new_sockfd = accept(sockfd, (struct sockaddr*)&pthread_arg->client_address, &client_len);
if(new_sockfd == -1) {
perror("accept");
free(pthread_arg);
exit(EXIT_FAILURE);
}
bzero(buffer, BUFFER_SIZE-1);
if((read(new_sockfd, &buffer, BUFFER_SIZE-1))<0) {
perror("read");
exit(EXIT_FAILURE);
}
pthread_arg->sockfd = new_sockfd;
pthread_arg->message=(char*)malloc(strlen(buffer));
if(!pthread_arg->message) {
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(pthread_arg->message, buffer);
pthread_arg->seconds = 0;
pthread_arg->delay = 0;
if(pthread_create(&thread, &pthread_attr, handler, (void*)pthread_arg) != 0) {
perror("pthread_create");
free(pthread_arg);
exit(EXIT_FAILURE);
}
}
shutdown(sockfd, SHUT_RDWR);
close(sockfd);
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define PORT 7507
#define SERVER "localhost"
#define BUFFER_SIZE 2048
int main(int argc, char *argv[])
{
int sockfd, bytes;
struct hostent* server_host;
struct sockaddr_in server_address;
char message_sent[BUFFER_SIZE];
char message_received[BUFFER_SIZE];
if(argc>1) {
printf("too many arguments\n");
exit(EXIT_FAILURE);
}
server_host = gethostbyname(SERVER);
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
memcpy(&server_address.sin_addr.s_addr, server_host->h_addr, server_host->h_length);
//socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
//connect
if (connect(sockfd, (struct sockaddr *)&server_address, sizeof server_address) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}
while(1) {
bzero(message_sent, sizeof(message_sent));
printf("Your message: ");
fgets(message_sent, BUFFER_SIZE-1, stdin);
message_sent[strcspn(message_sent, "\n")]=0;
//sending to server
if((write(sockfd, &message_sent, strlen(message_sent)))<0) {
perror("write");
exit(EXIT_FAILURE);
}
bzero(message_received, sizeof(message_received));
//reading from server
if ((read(sockfd, &message_received, BUFFER_SIZE-1))<0)
{
perror("read");
exit(EXIT_FAILURE);
}
printf("Server says: %s\n", message_received);
}
close(sockfd);
return 0;
}
OUTPUT in terminal:
For client:
Your message: message1
Server says: abcd
Your message: message2
Server says:
Your message: message3
Server says:
client automatically stops
For server:
Message received from client (thread id=x): message1
and here it stops, I dont see message2 and message3 received but the server is still running