c - 为什么我的服务器实现不能同时正确运行?

标签 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: Please input an string: 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);
}

最佳答案

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

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

从单独的(虚拟)终端启动服务器进程和客户端进程会让事情变得更清晰,这样它们的输出就不会混合。

关于c - 为什么我的服务器实现不能同时正确运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28616673/

相关文章:

scala - Scala 中的阻塞关键字

java - 如何限制 LinkedTransferQueue 的大小?

java - Hashmap 并发问题

c - 正常虚拟程序后标准输入未刷新

node.js - 使用 Node-Js 作为消息传递层

windows - 使用网络面板进行分析时,强制 Chrome 关闭/重新打开所有 TCP/TLS 连接

c# - 准备通过 TCPClient 流发送的序列化对象

c - 如何使用 "\a"转义字符发出蜂鸣声?

c - 如何通过2层函数修改结构体内容?

python - 为什么我无法执行存储在环境变量中的 shellcode?