记一次排查TCP连接出现RST问题

问题:

系统底层是C语言写的,目前从HP unix升级到Cent OS容器。

我们HP unix服务器以前接收客户端报文的逻辑是:三次握手->客户端发送请求报文->服务器处理完成之后发送应答报文->服务器发送FIN四次握手关闭。

现在CentOS抓包看下来的流程是:三次握手->客户端发送请求报文->服务器处理完成之后发送应答报文->服务器发送RST异常结束。

排查过程&思路:

中间进行了无数无效排查

两个服务器的流程不同在于最后的FIN包变成了RST包,所以我们在代码中的“服务器发送应答报文”成功之后,和在TCP连接close()关闭之前加上sleep(10),最后发现TCP连接的RST也同样延迟了10秒发送。

上面步骤就排查出了是TCP连接关闭的时候用RST替代了FIN,去网上查了下,close的时候发送RST包的原因可能是缓冲区中还有数据没有发送完或者接收完。

我们服务器发送的应答报文只有7个字节,接收的请求报文719个字节。所以不太可能是我们的TCP发送缓冲区中还有数据,极大可能是我们的接收缓冲区的数据没有读取完。

顺着这个思路,就排查代码中在接收客户端发送的请求包的时候recv()设置的socket缓冲区大小,发现是713,说明有6字节的数据还在缓冲区!最后接收缓冲区改成719后解决了。(正常的我们接收报文,应该是先接收请求包头,然后从请求包头中获取接收数据长度,以此来设置缓冲区,只是这个客户端报文比较特殊,是固定长度,所以在recv()的时候设置固定值。)

int ret = recv (int __fd, void *__buf, size_t __n, int __flags)
//fd:从文件描述符fd中读取数据。
//buf:用于接收数据的缓冲区。
//len:缓冲区长度。
//flags:指定调用方式,通常指定为0。

遗留问题:

至于为什么同样的代码,同样的接收缓冲区固定713,接收报文长度同样的719的,HP unix切换到CentOS就不行了, 猜测是厂商底层写的recv()接收的问题,或者是不同系统tcp连接处理方式不同的原因。

你可能感兴趣的:(tcp/ip,服务器,网络)