AI智能
改变未来

通过Java Socket编程观察内核级TCP的三次握手


客户端和服务端之间建立连接的三次握手是咋回事?

我们来从java代码运行到观察linux内核来稍微分析一下。

Socket Server与Client

Java代码先准备好上传到linux,server代码在虚拟机node1,client代码在虚拟机node2,从略。下面重点看一下client与server是如何建立连接的。

在server

node1

机器上抓取网卡(我的虚拟机网卡名是

ens33

)数据包

tcpdump -nn -i ens33 port 9090


启动服务端

还未accept,等待着输入

启动客户端

从Kernel级观察TCP建立连接的三次握手

上面服务端和客户端都启动以后,看一下

node1

内核网络状态

netstat -natp


可以看出,其中有两个9090端口,一个处理

LISTEN

监听状态,表示我服务端准备好了,任何客户端都可以来连我了;
还有一个是

established

表示已经建立连接状态,建立连接的双方是

192.168.134.128:9090

192.168.134.130:47904

,其中

192.168.134.128

是服务端,端口

9090

,有一个客户端

192.168.134.130

来连它并分配了一个随机端口

47904


但是,这个连接没有对应的进程PID,(server端还没有accept)。

再来看一下

tcpdump

抓包情况:

清楚地看到了客户端和服务端建立连接的三次握手。

本次socket的

四元组

可以看到是

CIP 192.168.134.130 CPORT 47904SIP 192.168.134.128 SPORT 9090

在server端按回车键,执行accept

accept后发现有Java进程,PID为3862

看下进程3862的文件描述(

lsof -p 3862

):

6u

建立连接

关注一下数据丢失的问题

当客户端一次性向服务端发送超过

MTU

的字节数时,超过的数据部分将会丢失。

关于

MTU

维基百科的解释:

最大传输单元(英语:Maximum Transmission Unit,缩写MTU)是指数据链接层上面所能通过的最大数据包大小(以字节为单位)。最大传输单元这个参数通常与通信接口有关(网络卡、串口等)。

常见媒体的MTU表

网络 MTU(Byte)
超通道 65535
16Mb/s令牌环 17914
4Mb/s令牌环 4464
FDDI 4352
以太网 1500
IEEE 802.3/802.2 1492
X.25 576
点对点(低时延) 296

查看本机网口的mtu

ifconfig


本机ens33网络mtu为1500,测试一下一次性发送超过1500个字节的情况

服务端等待接收消息(阻塞住了,还未accept)

客户端发送数据,随便粘贴一段文字,最后输入自己认得的1111111,

这个时候

netstat -natp

看一下连接情况

如图可知,此时接内核已接收了

1152

个,服务器还未accept,继续发送一段字符

abcdefg

,查看

netstat -natp

内核接收的还是

1152

个数据包,这时,让server端accept,发现接收到的数据后面的都丢失了。

Socket四元组

TCP是面向连接的,可靠地传输协议(三次握手),内核级开辟资源。

Socket四元组:

Client IP

Client Port

Server IP

Server Port

,这四个元素能让一个连接变得清晰、唯一。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 通过Java Socket编程观察内核级TCP的三次握手