问题
TCP socket keep-alive 失败,导致正在进行的业务失败。
分析
根据数据报文发现,每次tcp ack keep-alive数据报文请求发送后如果发送别的数据,就会出现socket超时, 判断是内核处理tcp keepalive出现问题导致的。
问题重现
我根据这种情况,实现了一个类似的socket,发送keep-alive然后在程序中sleep特定时间,然后发送数据,模拟紧跟着的情况,在正常Linux系统中是没有问题的,但是到了我们的设备中就出现问题了。
原因
Linux 发送keep-alive request的ack会有一个flag记录发送状态,如果收到了响应这个flag会被重置。这样在keep-alive timer到期后检测就不会出现问题,然而我们的内核中如果紧接着又数据报文发送,收到的ack会走另一条路径,这个flag不会被重置,导致的问题。
解决方案
就是将这个flag移到前面,不论收到的是正常的ack还是tcp keep-alive的ack都重置这个flag.