关于select函数的用法令人困惑的事情

时间:2016-02-26 07:06:24

标签: sockets networking

  1 #include "mynet.h"
  2 #include <sys/select.h>
  3 #include <sys/time.h>
  4 
  5 #define BUF_SIZE 100
  6 
  7 int main(int argc, char** argv)
  8 {
  9         int serv_sock, cli_sock;
 10         struct sockaddr_in serv_addr, cli_addr;
 11         struct timeval timeout;
 12         fd_set reads, cpy-reads;
 13 
 14         socklen_t cli_addr_size;
 15 
 16         int fd_max, str_len, fd_num, i;
 17 
 18         char buf[BUF_SIZE];
 19 
 20         if(argc!=2)
 21         {
 22                 printf("Usage: %s <port>\n", argv[0]);
 23                 exit(1);
 24         }
 25 
 26         serv_sock=Socket(PF_INET, SOCK_STREAM, 0);
 27 
 28         memset(&serv_addr, 0, sizeof(serv_addr));
 29 
 30         serv_addr.sin_family=AF_INET
 31         serv_addr.sin_port=htons(atoi(argv[1]));
 32         serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
 33 
 34         Bind(serv_sock, (sa*)&serv_addr, sizeof(serv_addr));
 35 
 36         Listen(serv_sock, 5);
 37 
 38         FD_ZERO(&reads);
 39         FD_SET(serv_sock, &reads);
 40         fd_max=serv_sock;
 41 
 42         while(1)
 43         {
 44                 cpy_reads=reads;
 45                 timeout.tv_sec=5;
 46                 timeout.tv_usec=5000;
 47 
 48                 if((fd_num=select(fd_max+1, &cpy_reads, 0, 0, &timeout))==-1)
 49                         break;
 50                 if(fd_num==0)
 51                         continue;
 52 
 53                 for(i=0; i<fd_max+1; i++)
 54                 {
 55                         if(FD_ISSET(i, &cpy_reads))
 56                         {
 57                                 if(i==serv_sock)
 58                                 {
 59                                         cli_addr_size=sizeof(cli_addr);
 60                                         cli_sock=Accept(serv_sock, (sa*)&cli_addr, &cli_addr_size);
 61                                         FD_SET(cli_sock, &reads);
 62 
 63                                         if(fd_max<cli_sock)
 64                                                 fd_max=cli_sock;
 65                                         printf("connected client: %d \n", cli_sock);
 66                                 }
 67                                 else
 68                                 {
 69                                         str_len=read(i, buf, BUF_SIZE);
 70                                         if(str_len==0)
 71                                         {
 72                                                 FD_CLR(i, &reads);
 73                                                 close(i);
 74                                                 printf("closed client: %d \n", i);
 75                                         }
 76                                         else
 77                                                 write(i, buf, str_len);
 78                                 }
 79                         }
 80                 }
 81         }
 82 
 83         close(serv_sock);
 84 
 85         return 0;
 86 }

我对上面的源代码有疑问,这在我的书的例子中。 我的问题是当有客户端连接到服务器时。

在这种情况下(有一些客户端),另一个坏客户端向服务器发送SYN数据包(不回复服务器的SYN / ACK数据包),因此select函数返回有关serv_sock的已发送消息。最后,因此,服务器将调用Accept()函数。但它被Accept()函数阻止,因为它是未完成的连接请求(与完成的连接请求形成对比,这是通过3次握手完成的。)

所以,这里,服务器被阻止Accept()功能。在这种情况下,当客户端向服务器发送消息时。服务器无法调用read()函数,因为它已被Accept()函数阻止。

我上面写的是对的???

1 个答案:

答案 0 :(得分:1)

  

我的问题是当有客户端连接到服务器时。

不,不是。您的问题与连接到服务器的客户端无关。它是关于无法完成与服务器的连接的客户端。

  

在这种情况下(有一些客户端),另一个坏客户端向服务器发送SYN数据包(不回复服务器的SYN / ACK数据包),因此select函数返回有关serv_sock的已发送消息。 / p>

不,它没有。你做了这个。当积压队列上存在完整连接时,它将返回。您的示例不是已完成的连接,也不是触发select().

的候选对象
  

最后,因此,服务器将调用Accept()函数。

没有。它仍将在select().

中被屏蔽
  

但是它被Accept()函数阻止了,因为它的未完成连接请求(与完成的连接请求形成对比,这是通过3次握手完成的。)

不,由于这个原因,它已被select()屏蔽了。

  

所以,这里,服务器被阻止接受Accept()函数。

没有

  

在这种情况下,当客户端向服务器发送消息时。服务器无法调用read()函数,因为它已被Accept()函数阻止。

没有

  

我上面写的是对的吗?

没有