Find the answer to your Linux question:
Results 1 to 4 of 4
I'm writing a simple chat client in C++ on linux to connect to a win32 chat server on my computer also written in C++. I'm confident that the server works ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Oct 2012
    Posts
    3

    Trouble with pipes in chat client on linux


    I'm writing a simple chat client in C++ on linux to connect to a win32 chat server on my computer also written in C++. I'm confident that the server works but the chat client is giving me some trouble. I'm forking the chat client and have one process dealing with incoming messages and another dealing with sending messages. I'm using two pipes in the chat client so each process can tell the other when it has terminated so the other process can go ahead and terminate. The pipes don't seem to be working though and I'm not sure where I'm going wrong. If you guys could take a look at my code I'd appreciate it. Maybe one of you will notice something I'm not doing right. Here's my code:

    Code:
    #define ChildRead pipefd1[0]
    #define ChildWrite pipefd2[1]
    #define ParentRead pipefd2[0]
    #define ParentWrite pipefd1[1]
    
    int main()
    {
      int nret, theSocket, theMode = 1, pipefd1[2], pipefd2[2];
      struct sockaddr_in server;
      char buf[2] = {0}, message[999] = {0}, ipAddy[20]= {0}, scrName[20] = {0};
      pid_t childpid;
    
      printf("Enter the IP address to connect to.\n\n");
      scanf("%s", ipAddy);
    
      printf("\nEnter your screen name.\n\n");
      scanf("%s", scrName);
    
      theSocket = socket(AF_INET, SOCK_STREAM, 0);
    
      if(theSocket < 0)
       printf("\nCouldn't create socket\n");
    
      memset(&server, 0, sizeof(server));
      server.sin_family = AF_INET;
      server.sin_addr.s_addr = inet_addr(ipAddy);
      server.sin_port = htons(8888);
    
      printf("\nAttempting to connect to %s\n", ipAddy);
    
      nret = connect(theSocket, (struct sockaddr *)&server, sizeof(server));
    
      if(nret < 0)
       printf("\nCouldn't connect\n");
    
      ioctl(theSocket, FIONBIO, &theMode);
    
      printf("\nConnected to server!\n\n");
    
      memset(message, 0, strlen(message));
    
      pipe(pipefd1);
      pipe(pipefd2);
    
      fcntl(ParentRead, F_SETFL, O_NONBLOCK);
      fcntl(ParentWrite, F_SETFL, O_NONBLOCK);
      fcntl(ChildRead, F_SETFL, O_NONBLOCK);
      fcntl(ChildWrite, F_SETFL, O_NONBLOCK);
    
      childpid = fork();
    
      if(childpid == 0)
      {
        close(ParentRead);
        close(ParentWrite);
    
        while(1)
        {
          read(ChildRead, &buf, 1);
    
          if(buf[0] == 'q')
          {
           close(ChildRead);
           close(ChildWrite);
           close(theSocket);
           exit(0);
          }
    
          if((nret = recv(theSocket, message, 999, 0)) < 1)
           continue; 
    
          if(message[7] == '~' && message[8] == 'q')
          {
            printf("\nChat server disconnected..\n");  
            write(ChildWrite, "q\0", 1);
            close(ChildRead);
            close(ChildWrite); 
            close(theSocket); 
            exit(0);
          }
    
          printf("%s\n", message);
    
          memset(message, 0, strlen(message));
        }
      }
      else
      {  
         strcpy(message, scrName);
         strcpy(&message[strlen(message)], ": ");
    
         close(ChildWrite);
         close(ChildRead);
    
         while(1)
         {
           read(ParentRead, &buf, 1);
    
           if(buf[0] == 'q')
           {
             close(ParentRead);
             close(ParentWrite);   
             close(theSocket);
             exit(0); 
           }
    
           scanf("%s", &message[strlen(message)]);
    
           if(strcmp(&message[strlen(scrName) + 2], "~q\0") == 0)
           {
             write(ParentWrite, "q\0", 1);
             close(ParentRead);
             close(ParentWrite);
             close(theSocket);
             exit(0);          
           }
    
           send(theSocket, message, strlen(message), 0);
    
           memset(&message[strlen(scrName) + 2], 0, strlen(&message[strlen(scrName) + 2]));     
         }  
      } 
    
      return 0;
    }

  2. #2
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,755
    Why use pipes? The process that forked can get signalled on the death of the spawned process (SIGCHLD), and the spawned (child) process will normally be terminated by the operating system automatically when its parent dies. Usually the parent process uses wait() or waitpid() to be informed when the child has died. If you just want to periodically check while doing something else, you can use waitpid(childpid, 0, WNOHANG) to check if it is still alive. This is necessary to avoid spawing zombie processes as well, in case the parent is going to hang around for awhile and possible spawn more children.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  3. #3
    Just Joined!
    Join Date
    Oct 2012
    Posts
    3
    Hi rubberman, thanks for responding to my post. I'm new to using fork and pipes. So, I didn't know about the various signals processes can receive or how to catch them. Anyhow, I've solved the problem I was having. It turns out that the pipes are working just fine. What was hanging my program was scanf. I forgot that scanf is a blocking function call. So, I changed that to fgets with the nonblock flag on the descriptor and everything is just fine. Thank you for your help though.

  4. $spacer_open
    $spacer_close
  5. #4
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,755
    Well, even using some communication medium (pipes in your case) is useful in normal shutdown situations, it still does not necessarily deal with unusual situations. You still need for the parent to use waitpid() as described in order to detect when the child process has terminated. A broken pipe may be due to the child terminating abnormally, or it could be some other cause. Inter-process communications and signalling (IPC) methods are key to robust client-server or peer-to-peer architectures. I've been doing that stuff for 30 years now, and it still bites me in the nether regions from time to time! Anyway, glad you sorted out your particular problem, and good luck!
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •