linux TCP服务器连接时发不出数据,断开瞬间发送全部数据

2019-03-26 12:34发布

本帖最后由 lzwml 于 2016-1-14 22:20 编辑

服务器和两个客户端连接,采用epoll非阻塞方式,客户端分别发送心跳包(6s一次),服务器发送心跳回应,接收在一个线程,人为操作服务器,每隔1S查询一次客户端业务情况,在另一个线程发送,此线程与接收线程未作互斥同步(Socket可能同时被两线程“写”)

所以服务器的两个线程大约每隔6一次数据冲突。(这是诱因
抓包发现的确出现有一定概率的数据冲突。


冲突后,接着服务器关闭1S的查询业务,网络上只心跳包和心跳回应包。
代码上看:
  • 每次客户端发心跳包后,服务器返回心跳回应都成功,这两种数据包都不大,都是40byte,不应该导致协议栈满
  • 问题是客户端收不到任何数据(这是我关注的问题)
抓包显示此时只有服务器端的TCP协议栈返回受到数据的ACK应答 ACK应答里并不包含心跳应答数据内容???
4.JPG
这种包好奇怪,命名负载在TCP头尾部,但wiresharp解析却放在Ethernet头尾部,对于padding第一次听说。
整个包长度60byte,其中6byte全0填在末端,54byte是Ethernet+IP+TCP头

  • 过了1min后客户端断开连接
抓包显示10次供400byte的心跳应答一次性发完


同事对最后一次发送的分析是:
TCP断开会有半连接状态,主动断开放问对方是否有数据要发,有就一次性发送。


大致的网络数据流程是这样
unnamed0.jpg


此帖出自Linux与安卓论坛
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
4条回答
lzwml
2019-03-27 01:20
本帖最后由 lzwml 于 2016-1-14 19:07 编辑

下面用Wireshark的分析Server与Client通信异常前后数据包状况

找到点线索,可能是TCP包错位【没有重传】导致
下面的图片是两组数据包处理重传的情况,
其中第一种处理了重传,另一个没有

54号数据(第14秒):序列号是117,下一个期望序列号(121)
1-1.JPG
66号数据(第22秒):错误(TCP Previous segment not capture)表示这个包(273)之前的包(121)没有收到,序列号错误。
121的数据包没有发送成功(该包可能路由走错了),序列号变成【273】不是(121)

同时67号数据(第22秒),纠正错误(重传TCP Retransmission

1.JPG
这样,通信一切正常

紧接着7S后又出现一次(TCP Previous segment not capture)错误
93号数据(第21秒):序列号421,下一个期望序列号(也是421,因为这个包是个【纯ACK】包)
104号数据(第27秒):(TCP Previous segment not capture)错误,序列号473,不是431
2.JPG
次后从115号数据(第33秒)到185号数据(第69秒)就是该帖子最开始描述的现象,server能收到client的心跳数据(整个帧长94byte,心跳内容40byte),server只返回纯ACK应答(帧长60byte),无心跳应答,持续30秒”

下面是拓扑图
3.JPG
我怀疑上面的两次数据错误是因为交换机数据转发错误,
因为在抓包端【偶尔】能收到192.168.1.254(服务器)发往192.168.0.6(另一台客户端)的流量

那么同样两次错误包也有可能将本该发往192.168.0.20(关注的客户端)的数据发往192.168.0.6(另一台客户端),
【并且】这之后还发生了什么????导致服务器不重发该数据包!!!!



一周热门 更多>