我正在用 C 语言测试一些代码,我发现 TCP 套接字调用的行为很奇怪。
-
我定义了一个同步接受客户端的侦听线程,在接受客户端后,它会在 for 循环中处理它,直到断开连接。因此,一次只处理一个客户端。所以我在循环中调用
accept
,然后在内部循环中recv
,直到收到空缓冲区。
我 用客户端触发 5 个线程,我调用
connect
、send
,最后close
我在任何通话中都没有收到错误。一切似乎都很好。
但是,当我在服务器端打印收到的消息时,结果发现只有第一个客户端进入服务器,即accept
永远不会在其他客户端上开火。
所以我的问题是:
connect
不应该等到服务器调用accept
吗?还是内核层在后台负责缓冲?- 如果不是这种情况,那么服务器是否应该无论如何都能够接受套接字,即使它处于断开连接状态?我的意思是预计它会丢失所有传入的数据吗?
- 还是我应该假设我的代码中存在错误?
TCP 状态机与客户端的状态机执行同步舞蹈。所有这些都是在操作系统级别(TCP/IP堆栈)执行的;用户空间进程只能不时地执行一些系统调用来影响此机器。一旦客户端调用listen()
此机器就会启动;并将建立新的联系。
还记得listen(int fd, int backlog)
的第二个参数吗?整个 3way 握手(通过 TCP 堆栈)完成,然后accept()
将 fd 传送到用户空间中的服务器。所以:套接字处于连接状态,但用户进程尚未拾取它们(通过调用accept()
)
不调用accept()
将导致内核对新连接进行排队。这些连接功能齐全,但显然数据缓冲区可能会填满,连接会受到限制。
推荐阅读:Comer& Stevens:使用TCP/IP 10.6-10.7的Internetworking(包含TCP状态图)