Linux C++ Socket Example with Client Server and Mulit-Threading

Aim
The aim of this Linux C++ example is to create simple client/server socket communication and multi-threading program on Linux. This shows the basics such as binding, listening and accepting sockets for Servers and connecting sockets for clients. Once the server accepts a socket, a thread is spawned to handle it. The threads are C++ POSIX threads. This is the simplest Linux C++ multi-threaded socket example you can find. Please leave any comments or questions at the end of this tutorial and I will endeavour to answer them. For a forking server look at Linux C++ Forking Server and Client Example.

Assumptions
This article assumes that you have a Linux based C++ compiler installed and configured. You can use cygwin if you do not have a Linux environment.

Versions used in this example
Sofware/ComponentImage
Fedora Core 5N/A
Links to these files can be found here

You can download the zipped example here.

Steps required for a server socket
  1. Initialize the socket using socket().
  2. Set any options such as blocking etc using setsockopt().
  3. Bind to the local address and port using bind(). For a server use INADDR_ANY as the address.
  4. listen() for connections.
  5. Go into a loop and accept connections usin accept(). Spawn threads (pthread_create) to handle these connections, so you can accept more connections.
    • Read and write to the socket. within the thread.
    • close()
    • When you are done, close the server socket using close()

    Steps required for a client socket
    1. Initialize the socket using socket().
    2. Set any options such as blocking etc using setsockopt().
    3. Connect to the remote host using connet(). Supply address and port here.
    4. Read and write to the socket. close()

    Write and compile the Server
    1. The server listens on port 1101 for a connection. When it receives a connection it creates a thread via pthread_create to handle it. This thread then reads from the socket, appends " SERVER ECHO" to it and sends it back to the client. As the server doesn't require an IP address, we assign INADDR_ANY to the sockaddr_in struct. Save this code as LinSever.cpp.
       1. #include <fcntl.h>
       2. #include <string.h>
       3. #include <stdlib.h>
       4. #include <errno.h>
       5. #include <stdio.h>
       6. #include <netinet/in.h>
       7. #include <resolv.h>
       8. #include <sys/socket.h>
       9. #include <arpa/inet.h>
      10. #include <unistd.h>
      11. #include <pthread.h>
      12. 
      13. void* SocketHandler(void*);
      14. 
      15. int main(int argv, char** argc){
      16. 
      17.     int host_port= 1101;
      18. 
      19.     struct sockaddr_in my_addr;
      20. 
      21.     int hsock;
      22.     int * p_int ;
      23.     int err;
      24. 
      25.     socklen_t addr_size = 0;
      26.     int* csock;
      27.     sockaddr_in sadr;
      28.     pthread_t thread_id=0;
      29. 
      30. 
      31.     hsock = socket(AF_INET, SOCK_STREAM, 0);
      32.     if(hsock == -1){
      33.         printf("Error initializing socket %d\n", errno);
      34.         goto FINISH;
      35.     }
      36.     
      37.     p_int = (int*)malloc(sizeof(int));
      38.     *p_int = 1;
      39.         
      40.     if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
      41.         (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
      42.         printf("Error setting options %d\n", errno);
      43.         free(p_int);
      44.         goto FINISH;
      45.     }
      46.     free(p_int);
      47. 
      48.     my_addr.sin_family = AF_INET ;
      49.     my_addr.sin_port = htons(host_port);
      50.     
      51.     memset(&(my_addr.sin_zero), 0, 8);
      52.     my_addr.sin_addr.s_addr = INADDR_ANY ;
      53.     
      54.     if( bind( hsock, (sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
      55.         fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",errno);
      56.         goto FINISH;
      57.     }
      58.     if(listen( hsock, 10) == -1 ){
      59.         fprintf(stderr, "Error listening %d\n",errno);
      60.         goto FINISH;
      61.     }
      62. 
      63.     //Now lets do the server stuff
      64. 
      65.     addr_size = sizeof(sockaddr_in);
      66.     
      67.     while(true){
      68.         printf("waiting for a connection\n");
      69.         csock = (int*)malloc(sizeof(int));
      70.         if((*csock = accept( hsock, (sockaddr*)&sadr, &addr_size))!= -1){
      71.             printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr));
      72.             pthread_create(&thread_id,0,&SocketHandler, (void*)csock );
      73.             pthread_detach(thread_id);
      74.         }
      75.         else{
      76.             fprintf(stderr, "Error accepting %d\n", errno);
      77.         }
      78.     }
      79.     
      80. FINISH:
      81. ;
      82. }
      83. 
      84. void* SocketHandler(void* lp){
      85.     int *csock = (int*)lp;
      86. 
      87.     char buffer[1024];
      88.     int buffer_len = 1024;
      89.     int bytecount;
      90. 
      91.     memset(buffer, 0, buffer_len);
      92.     if((bytecount = recv(*csock, buffer, buffer_len, 0))== -1){
      93.         fprintf(stderr, "Error receiving data %d\n", errno);
      94.         goto FINISH;
      95.     }
      96.     printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
      97.     strcat(buffer, " SERVER ECHO");
      98. 
      99.     if((bytecount = send(*csock, buffer, strlen(buffer), 0))== -1){
      100.         fprintf(stderr, "Error sending data %d\n", errno);
      101.         goto FINISH;
      102.     }
      103.     
      104.     printf("Sent bytes %d\n", bytecount);
      105. 
      106. 
      107. FINISH:
      108.     free(csock);
      109.     return 0;
      110. }
      Hide line numbers

    2. Open a prompt to the working directory and compile the code using your C++ compiler

      ..workspace\SocketExample>g++ -o server LinServer.cpp -lpthread

    Write and compile the Client
    1. The client reads a line from the console and sends this to the server. It then reads from the server and displays it on the console. Save this code as LinClient.cpp.
       1. #include <fcntl.h>
       2. #include <string.h>
       3. #include <stdlib.h>
       4. #include <errno.h>
       5. #include <stdio.h>
       6. #include <netinet/in.h>
       7. #include <resolv.h>
       8. #include <sys/socket.h>
       9. #include <arpa/inet.h>
      10. #include <unistd.h>
      11. 
      12. int main(int argv, char** argc){
      13. 
      14.     int host_port= 1101;
      15.     char* host_name="127.0.0.1";
      16. 
      17.     struct sockaddr_in my_addr;
      18. 
      19.     char buffer[1024];
      20.     int bytecount;
      21.     int buffer_len=0;
      22. 
      23.     int hsock;
      24.     int * p_int;
      25.     int err;
      26. 
      27.     hsock = socket(AF_INET, SOCK_STREAM, 0);
      28.     if(hsock == -1){
      29.         printf("Error initializing socket %d\n",errno);
      30.         goto FINISH;
      31.     }
      32.     
      33.     p_int = (int*)malloc(sizeof(int));
      34.     *p_int = 1;
      35.         
      36.     if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
      37.         (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
      38.         printf("Error setting options %d\n",errno);
      39.         free(p_int);
      40.         goto FINISH;
      41.     }
      42.     free(p_int);
      43. 
      44.     my_addr.sin_family = AF_INET ;
      45.     my_addr.sin_port = htons(host_port);
      46.     
      47.     memset(&(my_addr.sin_zero), 0, 8);
      48.     my_addr.sin_addr.s_addr = inet_addr(host_name);
      49. 
      50.     if( connect( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
      51.         if((err = errno) != EINPROGRESS){
      52.             fprintf(stderr, "Error connecting socket %d\n", errno);
      53.             goto FINISH;
      54.         }
      55.     }
      56. 
      57.     //Now lets do the client related stuff
      58. 
      59.     buffer_len = 1024;
      60. 
      61.     memset(buffer, '\0', buffer_len);
      62. 
      63.     printf("Enter some text to send to the server (press enter)\n");
      64.     fgets(buffer, 1024, stdin);
      65.     buffer[strlen(buffer)-1]='\0';
      66.     
      67.     if( (bytecount=send(hsock, buffer, strlen(buffer),0))== -1){
      68.         fprintf(stderr, "Error sending data %d\n", errno);
      69.         goto FINISH;
      70.     }
      71.     printf("Sent bytes %d\n", bytecount);
      72. 
      73.     if((bytecount = recv(hsock, buffer, buffer_len, 0))== -1){
      74.         fprintf(stderr, "Error receiving data %d\n", errno);
      75.         goto FINISH;
      76.     }
      77.     printf("Recieved bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
      78. 
      79.     close(hsock);
      80.     
      81. FINISH:
      82. ;
      83. }
      Hide line numbers

    2. Open a prompt to the working directory and compile the code using your C++ compiler

      ..workspace\SocketExample>g++ -o client LinClient.cpp


    Run the example
    1. Open a prompt to the working directory and run the server.

      ..workspace\SocketExample>server

    2. Open another prompt to the working directory and run the Client.

      ..workspace\SocketExample>client

    3. Now type something into the client prompt and press ENTER.
    4. You will see the exchange between client and server. You can open many client prompts at the same time and test.

    22 comments:

    jr said...

    Thanks for this example...It help me alot

    Anonymous said...

    The socket server leaks memory, in Ubuntu 10.04. Eash time I use the example client, then use ps v I see an increase in memory use (size) by 8 bytes.

    I was looking on the web for examples because my own server also leaks memory and since my program has to run continuously that will be fatal.

    righteous said...

    Yes, quite rightly so. I'm not calling pthread_detach or pthread_join and I should be doing either one of them. I will fix the example as soon as I can.

    Anonymous said...

    Hey , i would like to clarify regarding the server coding. You stated that to close the server port , we are to make use of close()? I tried using csock.close() but it dosnt seem to work for me. Am i getting it wrong? I used hsock.close() but im facing the same problem

    righteous said...

    These are linux sockets, csock and hsock are integers and not classes.

    To close use close(hsock).

    Anonymous said...

    in c is better to initialize and declare using:
    char host_name[]={"127.0.0.1"};
    than
    char* host_name="127.0.0.1";

    listen the compiler warning :)

    also you can avoid dangerous goto using return 1;

    righteous said...

    good oberservations. Goto is not dangerous.

    Remember this is just an example. Not production code :)

    dddddd said...

    thanx for the example.................

    hyd said...

    very good example of multiple client server program

    Anonymous said...

    it seems weird for me whenever i have multiple clients. it seems to kick the previous client out...

    what's the problem?

    Anonymous said...

    How would I broadcast a message to all clients from the server?

    Anonymous said...

    Thanks!, this example really help me ;)

    Anonymous said...

    should be close(*csock); or free(*csock); and not free(csock);

    rahul soni said...

    if there are 5 clients connected, how do I send a data to say 4th client ?

    righteous said...

    That's completely upto your implementation. Because it's multithreaded you can keep track of your clients through a global struct.

    Anonymous said...

    Thanks for this example it has help immensely, now I have a much better understanding. Also thanks to the supporting commentary as well.

    Anonymous said...

    Thank you very much. Saved me lots of time.

    Anonymous said...

    This is just what I needed to get started. Thanks!!!

    Anonymous said...

    Thank you for the example.

    Anonymous said...

    Could you please tell me how to implement this for making game that can be played over a network?

    Please reply asap!

    Anonymous said...

    how to add time in this c++? which mean at the client it display time...

    shanmukavel_profile said...

    Hello Sir,
    I am new for android. i trying for data transfer between computer and mobile phone via USB cable.
    Communication can be done two way:
    1) The first way is Socket,Protocol so like
    2) The Second way is Using USB functions
    ie, can be take example for in android USB HOST and USB Accessory Methods and in JAVA can also have JAVA HOST methods.
    Please sir,If you will have this code means send me sir,otherwise give some ideas and techniques of code..
    thank you sir…