三道经典的面试题
最近经常看到别人分享的关于网络通信socket三路握手的三道面试题, 之前看到时也不是很了解, 接下来通过代码和wireshark抓包来深入理解他们:
1, 在编写socket服务器端程序时,socket三路握手时在什么时候完成的?
2, listen()函数中第二个参数backlog的含义?
3, 客户端在进行三路握手时,出现异常将会收到什么报文?
服务器三路握手什么时候完成?
对于第一个问题, 按照自己之前的理解, 认为服务器端的三路握手时在accept()时完成的. 接下来我们通过代码和wireshark来抓包验证.
首先修改服务器程序, 在调用accept()之前加一个100s的延时, 在服务器休眠完成之前使用客户端连接, 同时启动wireshark开始抓包, 看是否能够完成三路握手.服务器端代码如下:
客户端进行连接, wireshark抓包结果:
我们可以观察到服务器端没有调用accept()函数, 通过抓包看到已经完成了三路握手, 证明了我们初步的想法是错误的.
接下来查阅 《unix网络编程》 这本书来看accept()函数的说明.
我们往前翻阅, 可以看到listen()函数中涉及到未完成连接队列与已完成连接队列, 以下为书中内容:
通过查阅, 我们可以得知, accept()函数在已完成连接队列列头返回下一个已完成连接,
服务器三路握手在listen()函数之后, accept()之前, 由内核来自动完成了三路握手.
listen()函数中第二个参数的含义?
在我们socket服务器端代码中, 调用socket, bind 之后, 服务器默认时主动连接模式, 此时调用listen函数.
listen()函数: 当socket创建一个套接口时, 它默认欸主动套接口, listen函数将未连接的套接口转换未被动套接口(即服务器变为被动连接模式), 第二个参数规定了内核未此套接口排队的最大连接个数. 书中内容如下:
通过listen()函数的backlog参数中, backlog的值是已完成连接队列与未完成连接队列之和(不包括accept之后拿出去的), 未完成连接条目有75秒的超时时间, 有模糊因子的存在, 最大值为乘以1.5, backlog值一般设置为13, 即最多可以有16个客户端.
客户端在进行三路握手时,出现异常将会收到什么报文?
对于这个问题, 我们在第一个问题中已经找到了三路握手的发生是在调用listen()函数之后, accept()函数之前.
对于这个问题, 首先修改服务器端代码, 在listen()函数之前给一个while(1) 死循环, 让他休眠! 我们通过客户端去连接, 同时启动wireshark开始抓包, 观察现象: 服务器端部分代码如下:
客户端进行连接, wireshark抓包结果:
通过观察现象可以发现, 我们在服务器端listen()函数之前进入死循环, 这时通过TCP Test Tool 客户端进行连接, 发生了三路握手中的第一次握手, 客户端发送了一个 SYN = 1, 此时三路握手发生异常, 服务器端给客户端发送 RST = 1, ACK = 1 的一个报文, 进行重连, 通过抓包可以看到一共重连了5次!!