【问题标题】:TCP: What happens when client connects, sends data and disconnects before acceptTCP:当客户端在接受之前连接、发送数据和断开连接时会发生什么
【发布时间】:2017-04-11 18:25:32
【问题描述】:

我正在用 C 语言测试一些代码,发现 TCP 套接字调用有奇怪的行为。

  1. 我定义了一个监听线程,它同步接受客户端,在接受客户端之后,它会在 for 循环中处理它,直到它断开连接。因此,一次只处理一个客户。所以我在循环中调用accept,然后在内部循环中调用recv,直到收到一个空缓冲区。

  2. 我使用客户端触发 5 个线程,我调用 connectsend,最后调用 close

  3. 我在任何呼叫中都没有收到任何错误。一切似乎都很好。

但是,当我在服务器端打印收到的消息时,结果发现只有第一个客户端通过服务器,即 accept 永远不会在其他客户端上触发。

所以我的问题是:

  1. 不应该connect 等到服务器调用accept 吗?还是内核层负责后台缓冲?
  2. 如果不是这种情况,那么服务器是否应该能够接受套接字,即使它处于断开连接状态?我的意思是它会丢失所有传入的数据吗?
  3. 或者我应该假设我的代码中存在错误?

【问题讨论】:

  • 还记得 listen(int fd, int backlog) 的第二个参数吗?在accept() 将 fd 传递到用户区的服务器之前,整个 3 次握手完成(由 TCP 堆栈)。所以:套接字处于连接状态,但用户进程还没有拿起它们(通过调用accept()
  • @joop 对。我现在明白了。所以数据被缓冲了。我没有看到输出的原因是因为我不小心锁定了服务器。所以,是的,谢谢你回答我的问题 1。我已经知道答案 2。
  • @joop 您可能想将其写为答案,以便我接受。

标签: c sockets tcp


【解决方案1】:

TCP 状态机与客户端的状态机执行同步舞蹈。所有这些都在操作系统级别执行(TCP/IP 堆栈);用户空间进程只能时不时地做一些系统调用来影响这个机器。一旦客户端调用listen(),这个机器就会启动;并且将建立新的连接。

还记得 listen(int fd, int backlog) 的第二个参数吗?在accept() 将 fd 传递到用户空间中的服务器之前,整个 3 次握手完成(由 TCP 堆栈)。所以:套接字处于连接状态,但用户进程尚未拾取它们(通过调用accept()

Not 调用accept() 将导致新连接被内核排队。这些连接功能齐全,但显然数据缓冲区可能会填满,连接会受到限制。

推荐阅读:Comer&Stevens:Internetworking with TCP/IP 10.6-10.7(包含 TCP 状态图)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    • 2014-07-05
    • 2021-11-13
    • 1970-01-01
    相关资源
    最近更新 更多