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