socket backlog底层原理

socket backlog底层原理

socket是什么?

socket一般翻译为套接字,它是应用层和传输层之间的一个抽象层,它将TCP/IP的复杂操作封装为几个简单接口,供应用层调用,来完成网络通信。此文中我们只讲解网络socket,不涉及unix socket。

其工作模式为:【open - read/write - close】

socket封装的函数有哪些?

int socket(int domain, int type, int protocol);int bind(int sockfd, conststruct sockaddr *addr, socklen_t addrlen);int listen(int sockfd, int backlog);int connect(int sockfd, conststruct sockaddr *addr, socklen_t addrlen);int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);ssize_t read(int fd, void *buf, size_t count);ssize_t write(int fd, constvoid *buf, size_t count);int close(int fd);

listen做了什么?

以上函数我们不展开说,后续的文章会详细讲解。

listen函数的第二个参数backlog就是本文的重点。

官方定义:

Now it specifies the queue length for completely established sockets waiting to be accepted,instead of the number of incomplete connection requests. The maximum length of the queue for incomplete sockets can be set using the tcp_max_syn_backlog sysctl. When syncookies are enabled there is no logical maximum length and this sysctl setting is ignored.If the socket is of type AF_INET, and the backlog argument is greater than the constant SOMAXCONN(128 default), it is silently truncated to SOMAXCONN.

所以此处backlog参数为用户态定义的已经建立连接的全连接队列长度。等待accepted。而不是未完成TCP连接的半连接队列长度。其中还有一个内核变量net.core.somaxconn,最终全连接队列长度等于min(backlog, net.core.somaxconn)。

整个事情是怎样的流程?

TCP建立连接是一个复杂的过程,通过三次握手,确定端和对端都具备读写能力。

连接流程请看下图

TCP三次握手

1,客户端发送SYN报文,客户端TCP状态SYN-SENT状态,如果服务端没有返回确认,执行重试。重试次数为net.ipv4.tcp_syn_retries。该配置可通过 cat /etc/sysctl.conf 查看。

2,服务端收到SYN报文,状态转换为SYN-RECV状态,并将连接句柄放到半连接队列中,同时返回SYN+ACK。半连接队列大小为net.ipv4.tcp_max_syn_backlog。如果半连接队列已满,服务端直接丢弃SYN。客户端自动重试。

3,客户端收到服务端SYN+ACK后,返回ACK报文,客户端状态修改为ESTABLISHED状态。

4,服务端收到ACK报文后,检查全连接队列是否已满,如果队列未满,则连接句柄放入全连接队列,服务端状态修改为ESTABLISHED状态。TCP三次握手成功。

如果全连接队列已满,当net.ipv4.tcp_abort_on_overflow为0,则丢弃ACK,并重发SYN+ACK,重试次数为net.ipv4.tcp_synack_retries。

当net.ipv4.tcp_abort_on_overflow为1,则收到ACK后,直接发RST段关闭连接,客户端一般报connection reset by peer的错误。

backlog的值该如何设置?

如果backlog值太小,在高并发的情况下,客户端的ack会被丢弃,并触发服务端重新发送SYN+ACK。客户端出现大量连接失败的情况。

如果backlog值太大,会产生大量的socket连接堆积。连接超时后,会导致write Broken pipe错误。也就是写失败。

所以该参数要根据业务场景,进行配置调优。

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。

http://www.vnetpros.com/style/images/nopic.gif
我要收藏
赞一个
踩一下
分享到

分享
评论
首页