Coding in linux example

How to Code a Server and Client in C with Sockets on Linux – Code Examples

In a previous example we learnt about the basics of socket programming in C. In this example we shall build a basic ECHO client and server. The server/client shown here use TCP sockets or SOCK_STREAM.

Tcp sockets are connection oriented, means that they have a concept of independent connection on a certain port which one application can use at a time.

The concept of connection makes TCP a «reliable» stream such that if errors occur, they can be detected and compensated for by resending the failed packets.

Server

Lets build a very simple web server. The steps to make a webserver are as follows :

1. Create socket
2. Bind to address and port
3. Put in listening mode
4. Accept connections and process there after.

/* C socket server example */ #include #include //strlen #include #include //inet_addr #include //write int main(int argc , char *argv[]) < int socket_desc , client_sock , c , read_size; struct sockaddr_in server , client; char client_message[2000]; //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 connection from an incoming client client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c); if (client_sock < 0) < perror("accept failed"); return 1; >puts("Connection accepted"); //Receive a message from client while( (read_size = recv(client_sock , client_message , 2000 , 0)) > 0 ) < //Send the message back to client write(client_sock , client_message , strlen(client_message)); >if(read_size == 0) < puts("Client disconnected"); fflush(stdout); >else if(read_size == -1) < perror("recv failed"); >return 0; >

The above code example will start a server on localhost (127.0.0.1) port 8888
Once it receives a connection, it will read some input from the client and reply back with the same message.
To test the server run the server and then connect from another terminal using the telnet command like this

Читайте также:  Amd a4 5000 linux

Client

Now instead of using the telnet program as a client, why not write our own client program. Quite simple again

/* C ECHO client example using sockets */ #include //printf #include //strlen #include //socket #include //inet_addr #include int main(int argc , char *argv[]) < int sock; struct sockaddr_in server; char message[1000] , server_reply[2000]; //Create socket sock = socket(AF_INET , SOCK_STREAM , 0); if (sock == -1) < printf("Could not create socket"); >puts("Socket created"); server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_family = AF_INET; server.sin_port = htons( 8888 ); //Connect to remote server if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0) < perror("connect failed. Error"); return 1; >puts("Connected\n"); //keep communicating with server while(1) < printf("Enter message : "); scanf("%s" , message); //Send some data if( send(sock , message , strlen(message) , 0) < 0) < puts("Send failed"); return 1; >//Receive a reply from the server if( recv(sock , server_reply , 2000 , 0) < 0) < puts("recv failed"); break; >puts("Server reply :"); puts(server_reply); > close(sock); return 0; >

The above program will connect to localhost port 8888 and then ask for commands to send. Here is an example, how the output would look

$ gcc client.c && ./a.out Socket created Connected Enter message : hi Server reply : hi Enter message : how are you

Server to handle multiple connections

The server in the above example has a drawback. It can handle communication with only 1 client. Thats not very useful.

One way to work around this is by using threads. A thread can be assigned for each connected client which will handle communication with the client.

/* C socket server example, handles multiple clients using threads */ #include #include //strlen #include //strlen #include #include //inet_addr #include //write #include //for threading , link with lpthread //the thread function void *connection_handler(void *); int main(int argc , char *argv[]) < int socket_desc , client_sock , c , *new_sock; 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); while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) ) < puts("Connection accepted"); pthread_t sniffer_thread; new_sock = malloc(1); *new_sock = client_sock; if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0) < perror("could not create thread"); return 1; >//Now join the thread , so that we dont terminate before the thread //pthread_join( sniffer_thread , 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 ) < //Send the message back to client write(sock , client_message , strlen(client_message)); >if(read_size == 0) < puts("Client disconnected"); fflush(stdout); >else if(read_size == -1) < perror("recv failed"); >//Free the socket pointer free(socket_desc); return 0; >

Run the above server and connect from multiple clients and it will handle all of them. There are other ways to handle multiple clients, like select, poll etc.

Читайте также:  Функциональные особенности операционной системы linux

We shall talk about them in some other article. Till then practise the above code examples and enjoy.

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected] .

64 Comments

  1. Zamer Chaudhary April 16, 2022 at 2:02 pm Hey sir i need you help related to Develop a client/server application using Linux TCP sockets and the C programming language.
    I will share the more information on mail. Please respond me.
    [email protected]
  1. Alex June 8, 2017 at 4:04 pm Yes, it fixes the bug with memory leakage but disables the multiple clients functionality, so this example doesn’t really work 🙁 I cann’t solve this problem yet.
  1. David November 5, 2021 at 1:01 am I’m wondering that, too. As soon as I change from the localhost address, I start getting message refused on the client.

Источник

Оцените статью
Adblock
detector