Linux socket

58 阅读4分钟

socket 是什么

socket 是用来对下层协议进行操作的,提供给应用层使用的一个抽象。

socket 在Linux 上的存在形式

Linux 上 一个socket 是以一个文件的形式存在的。

socket连接 与 socket

socket 是单纯的套接字。执行socket系统调用可以创建。创建了 socket,并不意味着建立了连接。执行connect系统调用建立连接。如果socket创建的时候,协议选择了tcp,那么建立socket连接的过程,其实就是建立tcp连接的过程,这时一个socket连接,其实就是一个tcp连接。

socket 的唯一性标志

协议类型 源地址 源端口 目标地址 目标端口

socket 缓冲区

socket 缓冲区的属性

  • 类型
  • 大小

tcp socket 缓冲区的类型

  • socket 接收缓冲区
  • socket 发送缓冲区

tcp socket 缓冲区的大小

查看当前某个 tcp socket 缓冲区的大小

通过 ss -amnt 可以 找到

  • tcp socket 发送缓冲区 所能分配的最大内存 snd_buf
  • tcp socket 发送缓冲区 已使用的内存 wmem_queued
  • tcp socket 发送缓冲区 已分配的内存 wmem_alloc
  • tcp socket 接收缓冲区 所能分配的最大内存 rcv_buf
  • tcp socket 接收缓冲区 已分配的内存 rmem_alloc 单位为字节
skmem:(r<rmem_alloc>,rb<rcv_buf>,t<wmem_alloc>,tb<snd_buf>,
                        f<fwd_alloc>,w<wmem_queued>,o<opt_mem>,
                        bl<back_log>,d<sock_drop>)

如何设置 tcp socket 的发送缓冲区大小 和 接收缓冲区大小

在应用层 可以设置 socket 的发送缓冲区 和 接收缓冲区 大小

问题: java socket setSendBufferSize() 设置了之后,运行程序,ss 发现socket的发送缓冲区是设置值的两倍,设置了3000,但是ss显示的是6000,这是什么原因?

 操作系统会将设置的缓冲区大小 ✖️ 2 

tcp socket 的发送缓冲区大小 和 接收缓冲区大小 是否有上限

是有的。内核参数 net.ipv4.tcp_rmem net.ipv4.tcp_wmem 的值的格式为 min default max 记录了最小值 默认值 和 最大值。设置的缓冲区的大小 不能配置的最大值。

Linux 如果不手动设置 tcp socket 的发送缓冲区大小 和 接收缓冲区大小 会如何

Linux内核 会根据情况 来自动调节 tcp socket 的发送缓冲区 和 接收缓冲区 的大小

Linux 是否有 关闭 自动调节tcp socket 发送缓冲区 和 接收缓冲区 的开关

内核参数 net.ipv4.tcp_moderate_rcvbuf 是 自动调节 tcp socket 接收缓冲区大小的开关 tcp socket 发送缓冲区自动调节大小需要在应用层手动关闭,没有内核参数作为它的开关。

tcp socket 缓冲区的 的作用是什么? 影响tcp 协议的哪一部分内容?

接收缓冲区的大小 会影响 发送的 tcp报文之中 接收窗口的大小。一般情况下 初始接收窗口的大小 = 接收缓冲区的大小 - (接收缓冲区的大小 * 2^ net.ipv4.tcp_adv_win_scale 参数值)

socket 监控

查看当前 tcp socket 缓冲区的 发送缓冲区 和 接收缓冲区的数据量

ss -nt 输出信息 Recv-Q Send-Q 表示 socket的接收缓冲区 和 发送缓冲区 的数据量。

socket 的编程模型

创建socket

socket 的创建 可以指定协议的类型tcp 或者udp, 还可以指定阻塞和非阻塞

从socket之中读取

1:socket的接收缓冲区为空。

从socket读取,如果接收缓冲区为空,socket非阻塞,则立刻返回。socket阻塞,等待接收缓冲区满了,或者接收缓冲区之中的数据存在PSH标志的报文后,读取数据返回(还可能存在其他条件导致 阻塞的读取返回,自己目前认知的是这两种)。

向socket 之中写入

向socket 写入,socket 发送缓冲区数据已满。socket非阻塞,则立刻返回。socket阻塞,等到发送缓冲区有空余空间后,将数据写入,然后返回。

关闭 socket

1: 关闭socket时,接收缓冲区不为空。 清空socket接收缓冲区之中的数据,清空发送缓冲区的数据,向对方发送RST报文。

2:关闭socket时,接收缓冲区为空,发送缓冲区不为空。 将FIN 报文 加入到发送缓冲区之中,等待剩余数据包的发出,以及四次挥手断开tcp连接。

问题

1:java new Socket()之后,进程会不会多出一个新的文件描述符 会的