声明:所有文章只作为学习笔记用,转载非原创
https://www.cnblogs.com/wn1m/p/10983172.html
https://www.cnblogs.com/f-ck-need-u/p/7623252.html
必要看看 关于 TCP 并发连接的几个思考题与试验
https://blog.csdn.net/solstice/article/details/6579232
https://blog.csdn.net/libaineu2004/article/details/40087167
![](https://img.haomeiwen.com/i20591801/c3ad0ed3f5336758.png)
![](https://img.haomeiwen.com/i20591801/6b067a246e36d539.png)
epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。
TCP协议栈维护着两个socket缓冲区:send buffer和recv buffer。
要通过TCP连接发送出去的数据都先拷贝到send buffer,可能是从用户空间进程的app buffer拷入的,也可能是从内核的kernel buffer拷入的,拷入的过程是通过send()函数完成的,由于也可以使用write()函数写入数据,所以也把这个过程称为写数据,相应的send buffer也就有了别称write buffer。不过send()函数比write()函数更有效率。
最终数据是通过网卡流出去的,所以send buffer中的数据需要拷贝到网卡中。由于一端是内存,一端是网卡设备,可以直接使用DMA的方式进行拷贝,无需CPU的参与。也就是说,send buffer中的数据通过DMA的方式拷贝到网卡中并通过网络传输给TCP连接的另一端:接收端。
当通过TCP连接接收数据时,数据肯定是先通过网卡流入的,然后同样通过DMA的方式拷贝到recv buffer中,再通过recv()函数将数据从recv buffer拷入到用户空间进程的app buffer中。
https://www.cnblogs.com/love-yh/p/7518552.html
socket()函数的作用就是生成一个用于通信的套接字文件描述符sockfd(socket() creates an endpoint for communication and returns a descriptor)。这个套接字描述符可以作为稍后bind()函数的绑定对象。
内核(kernel)利用文件描述符(file descriptor)来访问文件
在Linux操作系统中,可以将一切都看作是文件,包括普通文件,目录文件,字符设备文件(如键盘,鼠标...),块设备文件(如硬盘,光驱...),套接字等等,所有一切均抽象成文件,提供了统一的接口,方便应用程序调用
netstat命令的Send-Q和Recv-Q列表示的就是socket buffer相关的内容,以下是man netstat的解释。
Recv-Q
Established: The count of bytes not copied by the user program connected to this socket. Listening: Since Kernel 2.6.18 this column contains the current syn backlog.
Send-Q
Established: The count of bytes not acknowledged by the remote host. Listening: Since Kernel 2.6.18 this column contains the maximum size of the syn backlog.
对于监听状态的套接字,Recv-Q表示的是当前syn backlog,即堆积的syn消息的个数,也即未完成队列中当前的连接个数,Send-Q表示的是syn backlog的最大值,即未完成连接队列的最大连接限制个数;
对于已经建立的tcp连接,Recv-Q列表示的是recv buffer中还未被用户进程拷贝走的数据大小,Send-Q列表示的是远程主机还未返回ACK消息的数据大小。
之所以区分已建立TCP连接的套接字和监听状态的套接字,就是因为这两种状态的套接字采用不同的socket buffer,其中监听套接字更注重队列的长度,而已建立TCP连接的套接字更注重收、发的数据大小。
[root@xuexi ~]# netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp6 0 0 :::80 :::* LISTEN
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 ::1:25 :::* LISTEN
[root@xuexi ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 :22 :
LISTEN 0 100 127.0.0.1:25 :
LISTEN 0 128 :::80 :::
LISTEN 0 128 :::22 :::*
LISTEN 0 100 ::1:25 :::*
注意,Listen状态下的套接字,netstat的Send-Q和ss命令的Send-Q列的值不一样,因为netstat根本就没写上未完成队列的最大长度。因此,判断队列中是否还有空闲位置接收新的tcp连接请求时,应该尽可能地使用ss命令而不是netstat。
网友评论