客户端和服务端之间建立连接的三次握手是咋回事? 我们来从java代码运行到观察linux内核来稍微分析一下。
Java代码先准备好上传到linux,server代码在虚拟机node1,client代码在虚拟机node2,从略。下面重点看一下client与server是如何建立连接的。
在server node1
机器上抓取网卡(我的虚拟机网卡名是ens33
)数据包
tcpdump -nn -i ens33 port 9090
启动服务端
还未accept,等待着输入
启动客户端
上面服务端和客户端都启动以后,看一下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 47904
SIP 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 |
查看本机网口的mtuifconfig
本机ens33网络mtu为1500,测试一下一次性发送超过1500个字节的情况
服务端等待接收消息(阻塞住了,还未accept)
客户端发送数据,随便粘贴一段文字,最后输入自己认得的1111111,
这个时候netstat -natp
看一下连接情况
如图可知,此时接内核已接收了1152
个,服务器还未accept,继续发送一段字符abcdefg
,查看netstat -natp
内核接收的还是1152
个数据包,这时,让server端accept,发现接收到的数据后面的都丢失了。
TCP是面向连接的,可靠地传输协议(三次握手),内核级开辟资源。 Socket四元组:
Client IP
,Client Port
,Server IP
,Server Port
,这四个元素能让一个连接变得清晰、唯一。
- END -