为什么我的服务器实现不会正常并发运行?

时间:2015-02-19 20:53:00

标签: c tcp concurrency network-programming logic

我正在尝试使用unix系统调用fork创建一个可以处理多个并发连接的客户端/服务器系统。

客户端输入电影标题,服务器将检查电影是否存在。如果它在那里,它将告诉客户端排名,名称和盒子记录。

查看我的分叉实现,客户端要求用户输入,但程序只是简单地通过它。

输出示例:

connection made with client 127.0.0.1
PID IS 27270


 --> all messages read - connection being closed
CLIENT: Please input an string: PID IS 0

在此行,CLIENT:请输入一个字符串:PID IS 0,用户输入一个字符串,但程序会浏览它。如何让程序从客户端获取字符串?

服务器代码:

int main()
{
   int                sock, clientsock, mlen, addrsize, msgct, chc, chct, pid;
   struct sockaddr_in addr; //ipv4 address
   char                ch, buf[80];

   /*
    * Create a socket.
    */

   sock = socket(AF_INET, SOCK_STREAM,0); //create socket (AF_NET shows its ipv4 internet connection, SOCK_STREAM shows its a tcp)
   if (sock == -1)
   {   
      perror("opening socket");
      exit(-1);
   }

   //Bind socket to local address
   /*
    * Bind a name to the socket.  Since the server will bind with
    * any client, the machine address is zero or INADDR_ANY.  The port
    * has to be the same as the client uses.
    */

   addr.sin_family = AF_INET;
   addr.sin_port = htons (32351); //port number for local address
   addr.sin_addr.s_addr = htonl (INADDR_ANY); //ip address (you can also hard code it) 

   if (bind(sock, (struct sockaddr *) &addr, //binding, first parameter : is the socket you created, &addr is the 
      sizeof (struct sockaddr_in)) == -1) //error checking
   {  
      perror ("on bind");
      exit (-1);
   } //(at this moment we have binded socket)

   /*
    * Make the socket available for potential clients.
    */

   //if there is connection or not?
   if (listen(sock,1) == -1)  
   {  
      perror("on listen");
      exit(-1);
   }


   //-------Text File Implementation-----------
   FILE *fp;
   char data[5][200];

   char rank[5][2];
   char name[5][255];  
   char value[5][100];

   /* opening file for reading */
   fp = fopen("movie.txt", "r");
   if(fp == NULL) {
      perror("Error opening file");
      return(-1);
   }

   fgets (data[0], 200, fp);
   int i = 1;

   while(fgets (data[i], 200, fp)!=NULL)
   {
      /* writing content to stdout */
      sscanf(data[i],"%s %[^$] %s",rank[i],name[i],value[i]);
      puts(data[i]);
      i+=1;
   }

   //CODE DOES NOT IMPLEMENT AFTER THIS WHILE LOOP

   //close the file 
   fclose(fp);

   addrsize = sizeof(struct sockaddr_in);

   //THIS WHILE LOOP IS NOT BEING IMPLEMENTED...

   while(1)
   {
      clientsock = accept(sock, (struct sockaddr *) &addr, &addrsize);
      if (clientsock == -1)//error checking
      {  
         perror("on accept");
         exit(-1);
      }
      printf("connection made with client ");

      printf ("%s\n", inet_ntoa (addr.sin_addr)); //also print client address

      /* Create child process */
      pid = fork();
      if (pid < 0)
      {
         perror("ERROR on fork");
         exit(1);
      }

      if (pid == 0)
      {
         /* This is the client process */
         close(sock);

         bool exist = false;

         mlen = recv (clientsock, buf, 80, 0);
         if (mlen < 0)
         {
            perror("ERROR reading from socket");
            exit(1);
         }

         int lenS;
         int which;
         for(int i = 1; i<5; i++)
         {
            printf("%s\n\n", name[i]);

            char *pch = strstr(name[i],buf);

            if(pch != NULL)
            {
                which = i;
                exist = true;
                puts("GOOD");


            }
            else
            {
               puts("bad");
            }
         }

         if(exist)
         {

            //SEND TO CLIENT FROM HERE!
            printf("%s\n", rank[which]);
            printf("%s\n", name[which]);
            printf("%s\n", value[which]);

            lenS = strlen(name[which]);
            send (clientsock, name[which], lenS+1, 0);
         }
         else
         {
            //SEND TO CLIENT FROM HERE!!!!
            printf("NOT HERE ");
            send (clientsock, "NOT HERE", 9, 0);
         }

         printf("Here is the message: %s\n",buf);

         exit(0);
      }
      else
      {
         close(clientsock);
         printf(" --> all messages read - connection being closed\n");
      }
   }
}

客户代码:

int main()
{
   int                sock, addrsize;
   struct sockaddr_in addr;
   unsigned int       in_address;
   char buf[80];
   int mlen;

   /* 
    * Open a socket for Internet stream services.
    */

   sock = socket(AF_INET, SOCK_STREAM,0); //creating a socket to connect to server, AF_INET : ipv4 internet connection, SOCK_STREAM tcp
   if (sock == -1)
   {   perror("opening socket");
       exit(-1);
   }

   addr.sin_family = AF_INET; 
   addr.sin_port = htons (32351); //port number has to be the same as the one from server
   in_address = 127 << 24 | 0 << 16 | 0 << 8 | 1; //ip address, local host, since we are running client and server on the same computer, it needs to have the same ip address
   addr.sin_addr.s_addr = htonl (in_address);

   if (connect (sock, (struct sockaddr *) &addr,  //binding
       sizeof (struct sockaddr_in)) == -1)
   {   
      perror("on connect");
      exit(-1);
   } 

   char word[100];
   int len;

   printf("CLIENT: Please input an string: ");
   scanf("%s", word);

   //printf("You entered: %s\n", word);
   len = strlen(word);

   send (sock, word, len+1, 0);

   mlen = recv (sock, buf, 80, 0);
   printf ("%s\n\n\n\n\n\n\n", buf);

   /* 
    * Do a shutdown to gracefully terminate by saying - "no more data"
    * and then close the socket -- the shutdown is optional in a one way
    * communication that is going to terminate, but a good habit to get
    * into. 
    */

   if (shutdown(sock, 1) == -1)
   {  
      perror("on shutdown");
      exit(-1);
   }
   printf ("Client is done\n");
   close(sock);
}

1 个答案:

答案 0 :(得分:0)

您正在同一台计算机上运行客户端和服务器程序,并使用相同的控制终端。因此,服务器主进程,其客户端服务子进程和独立客户端进程都可以写入该终端。它们独立运行并同时运行,因此它们的输出可以被混淆。

在提示后发出PID IS 0消息并不表示客户端程序已跳过接受输入的事实,实际上,我不知道它是如何做的。提示和PID消​​息来自不同的进程。

从单独的(虚拟)终端启动服务器进程和客户端进程会使事情更加清晰,因此它们的输出不会混合。