场景:本地有一个客户端进程和一个服务器端进程,服务器端是自己写代码实现,而客户端端是其它组件。自己的进程和其它组件的区别就是自己的代码可以添加调试信息,而其它组件则不行,这也给调试带来了麻烦。现在的情况是,客户端向服务器端发送文件,服务器端需要应答200状态码,没收到应答客户端就会返回失败。现在我服务端应答逻辑如下:
int len;
char *resp = "200";
len = read(sockfd,buf, sizeof(buf));
if(len == 0)
{
ret = write(sockfd, resp, strlen(resp));
}
我是在read函数返回0的时候发送应答(read返回0,一般是对端已经关闭连接了,但是一开始我没意识到这个问题),然后客户端一直提示发送失败。于是我就用tcpdump抓了一下本地回环包看了下。
tcpdump -i lo port 16115 -c 10 -w ~/loop.cap
关于tcpdump的具体用法可以去百度,很多资料,这里主要说几点:
1、本地回环地址在Linux中的interface是叫lo,所以用-i指定抓lo的包
2、port是我服务器的端口,-c是指定抓几个包就结束本地抓包,-w是将抓到的包保存到loop.cap,可以导出来用wireshark分析
我将loop.cap导到wireshark中,如下:
发现,我发出去的应答包收到了客户端的RST应答,而在我发送应答之前,服务端就已经收到了客户端的FIN关闭连接的包,所以此时客户端已经处于半关闭状态,是没法接收到我的应答的。于是我将应答时间改在开始接收数据之前,就解决问题了,如下图: