使用套接字从客户端读取

时间:2010-03-03 03:14:06

标签: c unix sockets client

我基本上有一个服务器设置,我接受新客户端(UNIX),我正在使用select()命令等待文件描述符上的活动,但我不知道如何从客户端写入然后在服务器端阅读

FD_ZERO(&readfds);
FD_SET(server_sockfd, &readfds);
FD_SET(STDIN_FILENO, &readfds); 
while (1) {
   testfds = readfds;
   select(4 + MAXCLIENTS, &testfds, NULL, NULL, NULL);
   for (fd = 0; fd < 4 + MAX_CLIENTS; fd++) {
     if (FD_ISSET(fd, &testfds)) {
        if (fd == server_sockfd) { /* new connection request */
           client_sockfd = accept(server_sockfd, NULL, NULL);
           if (num_clients < MAXCLIENTS) {
              FD_SET(client_sockfd, &readfds);
              num_clients++;
           } else {
              sprintf(message, "XSorry, too many clients.  Try again later.\n");
              write(client_sockfd, message, strlen(message));
              close(client_sockfd);
           }
        } else if (fd == STDIN_FILENO) { 
           fgets(kb_message, BUFSIZ + 1, stdin);
           if (strcmp(kb_message, "quit\n") == 0) {
              sprintf(message, "XServer is shutting down.\n");
              for (fd2 = 4; fd2 < 4 + MAX_CLIENTS; fd2++) {
                 if (FD_ISSET(fd2, &readfds)) {
                    write(fd2, message, strlen(message));
                    close(fd2);
                 }
              }
              close(server_sockfd);
              exit(EXIT_SUCCESS);
           } else {
              sprintf(message, "M%s", kb_message);
              for (fd2 = 4; fd2 < 4 + MAX_CLIENTS; fd2++)
                 if (FD_ISSET(fd2, &readfds))
                    write(fd2, message, strlen(message));
           }
        } else { /* client leaving */
           close(fd);
           FD_CLR(fd, &readfds);
           num_clients--;
        }
     }
  }

}

我如何处理来自客户端的写入请求然后回写给它们,它是否在“其他”下面,我如何检查客户端是退出还是写入。

由于

4 个答案:

答案 0 :(得分:2)

select(2)最常见的错误是 没有重新初始化描述符集 ,因为第二个,第三个和第四个参数是输入 - 输出参数

设置fd_set,在外部循环之前读取,向其添加侦听套接字描述符,进入循环,制作此fd_set的副本并给出复制到select(2)。当新连接到达时,将其描述符添加到原始 fd_set。关闭套接字相同(read(2)上的错误或EOF) - 从原始 fd_set中删除描述符。

希望这有帮助。

答案 1 :(得分:1)

您认为在“其他”块中需要读取代码是正确的。如果文件描述符触发并且它不是标准输入或“连接”描述符,那么它是您尝试向您发送数据的客户之一。当在select中触发其中一个文件描述符时,需要在该描述符上调用“read”以将数据读入缓冲区。 read命令将返回读取的字节数。如果这是一个正数,则表示客户端已向您发送数据。如果它为零,则表示客户端已结束与服务器的TCP连接。

else块看起来像:

 else 
  {
     //Existing connection has data for us to read
     if((nBytes = read(fd, buffer, MAXBUFFER)) <= 0) 
     {
        if(nBytes == 0)
        {
          //Actually, its sending us zero bytes, connection closed
          printf("Socket %d hung up\n", fd;
        }
     else
          printf ("Read Error"\n)
  }

另外,按照上面的Nikolai N Fetissov的建议,确保当客户端连接时将fd存储在永久fd_set结构中,因为正在使用的那个正在被select调用修改。

答案 2 :(得分:0)

您的问题可能是您有一个名为read的变量。它将掩盖你需要使用的一个hte函数 - read()系统调用以从套接字中获取数据。客户端将其放入write()。您可能还想检查select()的返回值,它将告诉您有多少文件描述符可供阅读。然后,您可以使用FD_ISSET()检查哪些。看起来你已经在做那个部分了(除了你似乎正在检查错误的变量?)...只需在该文件描述符上调用read()以获取客户端编写的数据。

答案 3 :(得分:0)

else 
{
  bzero(buf,100);
     n=read(i,buf,100); // Read the client message 
            buf[n]='\0';
       if(n==0) // Check the client is closed or not 
      {

              printf("%d is closed\n",i);
              close(i);
              FD_CLR(i, &master);
              if(i==fdmax)
              fdmax--;

       }
       else
       {
            n=strlen(buf);

        write(1,buf,n);
        fflush(stdout);

          write(1,"Enter the message\n",18);
          bzero(buf,100);
          read(0,buf,100);
            buf[n]='\0';
          write(i,buf,n);
          fflush(stdout);
       }
    } 

注意:     接受客户端后,在fd集中添加客户端。     然后从客户端读取消息     如果消息等于0,则关闭客户端。     如果要使用客户端fd将消息发送到客户端,则可以发送到客户端