C - Creating endless socket connection between server and client (Linux)

11,841

Solution 1

The problem with your server is that you immediately terminate whenever you receive a message. What you should do is keep on listening with the recv() function until the client disconnects. Here is one piece of code that should do the trick.

Disclaimer: However I haven't tested it, it's from an old project that I modified for you on the fly it's supposed to work but I'm not 100% sure it does, I have no time to test it right now but feel free to ask questions if there is something wrong, I'll try to correct it.

EDIT: trying to re-bing causes an error because the binding is already done and the port is already busy so you cannot "assign" an other program to this port therefore giving you an error. The only thing that you have to do is make sure that your server listens until the client disconnects from the server.

Also, it is possible that some of the code was made for c++ at some point, but the networking part should work just fine.

Feel free to try it out and comment if you have questions. Server.c:

    int socket_desc , client_sock , c , *new_sock;
    struct sockaddr_in server , client;

    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        //HANDLE ERROR
    }
    printf("Socket created\n");

    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( 8000 );

    //Binding, you already do it correctly.
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server))< 0)
    {
        //ERROR
    }
    printf("bind done");

    //Listen
    listen(socket_desc , 3);

    printf("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 = (int*) malloc(1);
        *new_sock = client_sock;

        if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void*) new_sock) < 0)
        {
            //ERROR
        }

        printf("Handler assigned");
    }

    if (client_sock < 0)
    {
        //ERROR
    }

    //return 0;

}

/*
 * This will handle connection for each client you may have and read indefinitely
 * */
void *connection_handler(void *socket_desc)
{
    //Get the socket descriptor
    int sock = *(int*)socket_desc;
    int read_size;
    char *message , client_message[2000];
    string smatrix ;
    int ind ;
    string tok ;
    int i = 0 ;


    //Receive a message from client
    while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
    {
        //What you want to do with the client's message
    }

    if(read_size == 0)
    {
        printf("Client disconnected");
        fflush(stdout);
    }
    else if(read_size == -1)
    {
        //ERROR
    }

    //Free the socket pointer
    free(socket_desc);

As for the client, do a while loop until a certain time has passed or a given character or value is entered. Something like:

while(wantToExit == false){
   char a;
   printf("Please enter a char");
   scanf("%c", &a);
   write(sock , a , 1); //Note use strlen() for strings
}

Hope it helps

Solution 2

What do you actually expect the server to do? You open/read/terminate. Termination, of course closes the socket implicitly - luckily, as you forgot to close explicitly.

You have to constantly read from the socket. Not sure what you mean by "it ...gives me an Error on binding"; if you try to re-bind, that is of course wrong. You would not open a file again and again, and ... just to read its data.

If you want to listen on the socket after it has been closed from the other side, just have listen in an outer loop.

Read Wikipedia for basics about sockets and check the links.

Share:
11,841
Hassan Yousuf
Author by

Hassan Yousuf

Updated on June 04, 2022

Comments

  • Hassan Yousuf
    Hassan Yousuf almost 2 years

    I have a simple socket program created in C (using Ubuntu), the connection works fine, server compiles and client provides the IP and port number.

    But when the connection is established, the client can only send one message and then the connection closes. When the client sends the message, the server receives it and the program ends by itself.

    I tried to use a while loop, but then it gives me an Error on binding. Is there any way to make it infinite, so that when user enters exit or some specific key/command, the program ends.

    server.c UPDATED with WHILE LOOP

    #include<stdio.h>  
    #include<stdlib.h>  
    #include<sys/types.h>     
    #include<sys/socket.h>  
    #include<netinet/in.h>  
    #include<string.h>  
    
    int main(int argc, char *argv[])  
    {  
          int sockfd, newsockfd, portNum, clien, n;
          char buffer[256];
          struct sockaddr_in serv_addr,cli_addr;
      if (argc < 2)
      {
            fprintf(stderr, "\nno port provided");
            exit(1);
      }
    
      sockfd = socket(AF_INET,SOCK_STREAM, 0);
      if (sockfd < 0)
            printf("\nprovide a valid port number\n");
    
      bzero((char *)&serv_addr, sizeof(serv_addr));
      portNum = atoi(argv[1]);
    
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_addr.s_addr = INADDR_ANY;
      serv_addr.sin_port = htons(portNum);
    
      if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
            printf("error on binding");
    
      while(1)
      {
           listen(sockfd,5);
      }
      clien = sizeof(cli_addr);
      newsockfd=accept(sockfd, (struct sockaddr *) &cli_addr, &clien );
    
      if (newsockfd < 0)
            printf("=> Error on accepting...\n");
    
      bzero(buffer, 256);  
      n = read(newsockfd, buffer, 256); 
    
      if (n < 0)  
            printf("error reading from socket...\n");
    
      printf("%s\n", buffer);
      n = write(newsockfd, "message received.", 58);
    
      if (n < 0)
            printf("cannot write from socket...\n");
    
      return 0;
    }
    

    client.c UPDATED with WHILE LOOP

    #include<stdio.h>  
    #include<stdlib.h>  
    #include<sys/types.h>     
    #include<sys/socket.h>  
    #include<netinet/in.h>  
    #include<netdb.h>  
    #include<string.h>  
    
    int main(int argc, char *argv[])  
    {  
          int sockfd,portno,n;
          char buffer[256];
          struct sockaddr_in serv_addr;
          struct hostent *server;
    
          //while(counter != 5)
          // /{
                if (argc < 3)
          {  
                fprintf(stderr,"Usage %s hostname port...\n",argv[0]);
                exit(1);
          }
    
          portno = atoi(argv[2]);
          sockfd = socket(AF_INET, SOCK_STREAM, 0);
          if (sockfd < 0)
                printf("\error opening socket...\n");
    
          bzero((char *) &serv_addr, sizeof(serv_addr));
          server = gethostbyname(argv[1]);
    
          if (server == NULL)
          {
                fprintf(stderr,"no such host...\n");
                exit(0);
          }
    
          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, &serv_addr,sizeof(serv_addr)) <0 )  
                printf("\error connecting\n");
    
          printf("your message:");
          fgets(buffer, 256, stdin);
          while(1)
          {
                n = write(sockfd,buffer,strlen(buffer));
          }
          if (n < 0)
                printf("error writing to socket\n");
    
          n = read(sockfd, buffer, 255);
    
          if (n < 0)
                printf("error reading from socket\n");
    
          printf("%s\n", buffer);          
    
          return 0;
    }
    

    Thank you.

  • Hassan Yousuf
    Hassan Yousuf almost 9 years
    I added a while loop to my listen() but now the client keeps on sending messages but doesn't outputs on the server screen, server.c is also running but doesn't output anything. How do I make the program terminate when the client enters "exit". I need to add some condition like while(msg != 'exit')
  • Hassan Yousuf
    Hassan Yousuf almost 9 years
    I added a while loop to my server/client code it is now endless but now when client sends message, the server is not displaying it. How do I display them. You're while loop made my code work but how can I terminate the program when user enters "exit"?
  • too honest for this site
    too honest for this site almost 9 years
    IIRC, the read only returns with 0 bytes read, if the link has been closed. But what do you actually want? You wrote you want ot keep the server running, now you want to terminate when the client disconnects. Pick one. And read about socket programming. It is all in the docs. Please understand this is not a tutorial site.
  • too honest for this site
    too honest for this site almost 9 years
    For the termination on command: Just end the while loop when you recieve the corresponding message.
  • too honest for this site
    too honest for this site almost 9 years
    @moose: Standard warning: do not cast void *. This is legacy stuff and strongly deprecated. It will suppress compiler warnings do to invalid types. Read here. Note the compiler is your friend.
  • Hassan Yousuf
    Hassan Yousuf almost 9 years
    I want to end the connection when the clients types 'exit' how do I do that? Doesn't the server receives the message in packets/bytes?
  • too honest for this site
    too honest for this site almost 9 years
    Sockets provide an octet stream. Just have the messages defined as you need them. There is no difference from the other messages. Just check if that is your exit-message and end the loop. Please do some research on your own!
  • LBes
    LBes almost 9 years
    @moose well you will have to scan the client's message and whenever exit is sent you terminate the server loop. But that should be an other question on here. Please accept my answer if it helped
  • Hassan Yousuf
    Hassan Yousuf almost 9 years
    @LonniBesançon Thanks man! it works fine now. I added a while loop the wrong way. But now it's receiving fine. Thank you!