Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple socket server in C using threads (pthread library) Compiles on linux
/*
C socket server example, handles multiple clients using threads
Compile
gcc server.c -lpthread -o server
*/
#include<stdio.h>
#include<string.h> //strlen
#include<stdlib.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h> //write
#include<pthread.h> //for threading , link with lpthread
//the thread function
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c;
struct sockaddr_in server , client;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
pthread_t thread_id;
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
if( pthread_create( &thread_id , NULL , connection_handler , (void*) &client_sock) < 0)
{
perror("could not create thread");
return 1;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join( thread_id , NULL);
puts("Handler assigned");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size;
char *message , client_message[2000];
//Send some messages to the client
message = "Greetings! I am your connection handler\n";
write(sock , message , strlen(message));
message = "Now type something and i shall repeat what you type \n";
write(sock , message , strlen(message));
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
//end of string marker
client_message[read_size] = '\0';
//Send the message back to client
write(sock , client_message , strlen(client_message));
//clear the message buffer
memset(client_message, 0, 2000);
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
return 0;
}
@jybaek

This comment has been minimized.

Copy link

jybaek commented Mar 16, 2017

Hello? I accidentally saw your code, but there are two things that are wrong. First, the used socket is not closed. Second, you have to rethink the return type of pthread_create and modify line 62.

if( pthread_create( &thread_id , NULL ,  connection_handler , (void*) &client_sock) < 0)

thanks

@MAZHARMIK

This comment has been minimized.

Copy link

MAZHARMIK commented May 25, 2017

Why have you used thread ? Is this because that this code will help to accept multiple client requests ?
I need help in this. Will you please answer me as soon as possible

@MAZHARMIK

This comment has been minimized.

Copy link

MAZHARMIK commented May 25, 2017

If I run this multi threaded server in one terminal and two or three clients in other terminals, and lets say, client1 sent a message and client2 also sent a message, and after that if the server replies then how would I know which client is being sent the message. I wrote a client as shown below and run this multi threaded server . I am stuck in the confusion I mentioned above. Please help me out with this.
`//client:
#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>

int main()
{
int socket_desc, val;
struct sockaddr_in client_addr;
char buffer[256];
socket_desc = socket(AF_INET, SOCK_STREAM, 0);

printf("Enter the port number\n");
int port;
scanf("%d", &port);
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr =  INADDR_ANY; 
client_addr.sin_port = htons(port);

if(connect(socket_desc, (struct sockaddr*)&client_addr, sizeof(client_addr)) == 0)
	printf("CONNECT STATE: Connected to Server on port %d\n", port);
else
	printf("Connection to server failed !\n");

while(1) 
{
	
	printf("Message to server: ");
	bzero(buffer,256);
	scanf("%s", buffer);
	
	write(socket_desc,buffer,strlen(buffer));
	bzero(buffer,256);
	
	read(socket_desc,buffer,255);
	printf("Message from server: %s\n",buffer);
	
}
	close(socket_desc);
	return 0;	

}`

@nwork

This comment has been minimized.

Copy link

nwork commented Nov 12, 2017

@MAZHARMIK
in regards to your question from my own research use "recvfrom()" and "sendto()"

@Francoisbeche

This comment has been minimized.

Copy link

Francoisbeche commented Jan 27, 2018

@MAZHARMIK

You can see , the function connection_handler from server take a socket_desc as paramater, so when you accept is beeing called you can for example create a struct representing a client with all information like IP, FD etc.. and stock it in an array, so you can read this array from your thread and know which client is by using your FD as array's index.

@maartenintel

This comment has been minimized.

Copy link

maartenintel commented May 2, 2018

Better to pass the accepted socket to the thread by value rather than by reference since there might be two accept()s before connection_handler() runs. When this happens, the second accept() overwrites client_socket before connection_handler() can grab it into sock at line 88 and both threads will get the same socket descriptor. Two threads servicing the same socket is problematic.

@praveen-nair

This comment has been minimized.

Copy link

praveen-nair commented May 16, 2018

I see that you have a commented pthread_join (//pthread_join( thread_id , NULL);) So now you are creating 'n' number of threads and not closing the. Why don't you keep an array (thread pool) to save the thread state and clear it as soon as the connection_handler job is completed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.