Accept建立连接

三次握手过程

  1. 服务端绑定和监听某个端口,创建SYN队列和ACCEPT队列;
  2. 客户端调用connect()发起连接,发送SYN包到服务端,状态变为SYN_SEND;
  3. 服务端监听到连接请求后,连接先被放入SYN队列(即未完成握手队列)中,同时返回SYN+ACK包给客户端,状态变为SYN_RCVD;
  4. 客户端收到SYN+ACK包之后,状态变为ESTABLISHED,并发送ACK包到服务端;
  5. 当服务端收到ACK包之后,将连接从SYN队列转移到ACCEPT队列,状态变为ESTABLISHED;
  6. 服务端调用accept()从ACCEPT队列获取已建立的连接进行处理;

这里写图片描述

SO_BACKLOG与ACCEPT队列大小关系

  SO_BACKLOG指定了bind接口入参backlog的大小,而ACCEPT队列大小由底层系统实现决定,不一定是backlog设定的值。在Linux中,内核会根据传入的backlog参数与系统参数somaxconn(查看/proc/sys/net/core/somaxconn),取二者的较小值(待确认)。在netty实现中,backlog默认通过NetUtil.SOMAXCONN指定。

public abstract ServerSocketChannel bind(SocketAddress local, int backlog)
        throws IOException;

The backlog parameter is the maximum number of pending connections on the socket. Its exact semantics are implementation specific. In particular, an implementation may impose a maximum length or may choose to ignore the parameter altogther. If the backlog parameter has the value, or a negative value, then an implementation specific default is used.

应用执行accept()速度过慢

  如果应用进程中调用accept获取新连接的代码段长期得不到执行,ACCEPT队列会变满,导致客户端的连接请求被拒绝。

accept()使用方式

  • 阻塞模式。使用单独的线程执行accept(),适用于有海量连接的场景;
  • 非阻塞模式。执行accept()的线程还会执行其他操作,适用于连接少,非阻塞操作的场景;

参考:

  1. https://www.jianshu.com/p/e6f2036621f4
  2. https://blog.csdn.net/russell_tao/article/details/9111769

猜你喜欢

转载自blog.csdn.net/yangguosb/article/details/80077351
今日推荐