2

我正在使用 select() 进行非阻塞 TCP 套接字编程。

正常设置后,

socket()
make socket non-blocking
bind()
listen()
FD_ZERO
FD_SET
  ...
select()

FD_ISSET
  ...
  s = accept()

出于某种原因,在 FD_ISSET 之后服务器做了一些准备但随后选择不接受。简单的方法就是在 accept() 之后关闭 s。但是在accept()之前,有没有办法告诉客户端这个连接应该失败呢?谢谢你。

4

1 回答 1

4

不,如果你得到一个传入连接并且你根本不想要它,你将不得不立即这样accept()close()。这不是 TCP(或其他网络协议)工作方式的结果,而是套接字 API固有的。

假设我们正在谈论 TCP/IP,请注意,当select()poll()或其他)通知您侦听套接字已准备好读取时,不接受连接已经为时已晚:内核已经接受代表您的连接。也就是说,它已经发出了一个SYN|ACK响应传入的SYN数据包。这实际上是listen()系统调用的效果。之后,调用accept()只是一种形式:它为接受的连接分配一个新的文件描述符。

可能利用不同的做事方式的最值得注意的软件是TCP 包装器。TCP 包装器通常仅根据远程 IP 地址来决定是否接受传入连接。如果它有机会做出这个决定并在连接被接受之前拒绝连接,那么它将使 TCP 包装器拒绝连接的客户端能够获得真正的“连接被拒绝”响应(RST对数据包的响应SYN,只是就像没有在端口上监听一样)。但是对于套接字接口,它没有办法做到这一点。而是打开客户端的连接,然后立即关闭。

并非所有操作系统都以这种方式相同。例如,在 Cisco IOS 上,当您在 vty 端口上配置访问列表以允许来自某些 IP 地址的传入连接并拒绝来自其他地址的传入连接时,被拒绝的连接会得到真正的“连接被拒绝”。但它不是使用套接字实现的。(它可能是使用非常专有的东西实现的。)

于 2013-02-01T21:27:15.917 回答