TCP:客户端在接受之前连接、发送数据和断开连接时会发生什么 [英] TCP: What happens when client connects, sends data and disconnects before accept

查看:40
本文介绍了TCP:客户端在接受之前连接、发送数据和断开连接时会发生什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 C 测试一些代码,我发现 TCP 套接字调用出现了奇怪的行为.

I'm testing some code in C and I've found strange behaviour with TCP socket calls.

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

  1. I've defined one listening thread which accepts clients synchronously and after accepting the client it process it in a for loop until it disconnects. Thus only one client at a time is handled. So I call accept in a loop and then recv in an inner loop until received an empty buffer.

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

I fire 5 threads with clients, I call connect, send and finally close

我在任何通话中都没有收到错误消息.一切似乎都很好.

I get no error in any call. Everything seems to be fine.

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

However when I print received message on the server side it turns out that only the first client got through to the server, i.e. accept never fires on other clients.

所以我的问题是:

  1. 不应该connect 等到服务器调用accept 吗?还是内核层负责在后台进行缓冲?
  2. 如果不是这种情况,那么服务器是否应该无论如何都不能接受套接字,即使它处于断开连接状态?我的意思是它会丢失所有传入的数据吗?
  3. 或者我应该假设我的代码中存在错误?
  1. Shouldn't connect wait until server calls accept? Or is the kernel layer taking care of buffering under the hood?
  2. If it's not the case then shouldn't the server be able to accept the socket anyway, even if it is in a disconnected state? I mean is it expected to lose all the incoming data?
  3. Or should I assume that there's a bug in my code?

推荐答案

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

The TCP state-machine performss a synchronized dance with the client's state machine. All of this is performed at OS-level (The TCP/IP stack); the userspace process only can do some systemcalls to influence this machinery now and then. Once the client calls listen() this machinery is started; and new connections will be establisched.

还记得 listen(int fd, int backlog) 的第二个参数吗?整个 3way 握手在 accept() 将 fd 传送到用户区的服务器之前(由 TCP 堆栈)完成.所以:套接字处于连接状态,但用户进程还没有选择它们(通过调用 accept() )

Remember the second argument for listen(int fd, int backlog) ? The whole 3way handshake is completed (by the TCP stack) before accept() delivers the fd to the server in userland. So: the sockets are in connected state, but the user process hasn't picked them up yet (by calling accept() )

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

Not calling accept() will cause the new connections to be queued up by the kernel. These connections are fully functional, but obviously the data buffers could fill up and the connection would get throttled.

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

Suggested reading: Comer& Stevens: Internetworking with TCP/IP 10.6-10.7 (containing the TCP state diagram)

这篇关于TCP:客户端在接受之前连接、发送数据和断开连接时会发生什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆