是这样的: 一个游戏tcp服务,没有什么特殊配置: const server = require('net').createServer(app.callback());
服务端处理流程是这样的:服务端发完最后一个数据包后,服务端调用destroy方法关闭socket。 线上发现,会有机率出现最后一个数据包丢失的情况(前端没收到最后一个数据包),通过前端日志发现,出现问题时,前端是先收到了close事件,后续就没有了。
猜想:当调用destroy, 不会把socket发送缓冲区flush到对端,运气好的时候,destroy之前,最后一个数据发送完了,就没问题;运气不好就丢弃了。翻开node文档,里面写了:
Use end() instead of destroy if data should flush before close, or wait for the 'drain' event before destroying the stream.
于是把destroy改为end,心想一定没问题了。然而,又出现了(但概率要小很多),前端还是有机率收不到最后一个数据包。 又一次猜想: 1、Use end() instead of destroy if data should flush before close, or wait for the 'drain' event before destroying the stream. 这句话的意思是调用end(data),把data flush进内核发送缓冲区,不是说从内核发送缓冲flush到对端,在close时,还是一个丢弃了发送缓冲; 2、在调用close后,触发服务端close事件,在close事件里将socket = null,socket失去引用,被gc了,而销毁socket对象时, 丢弃了发送缓冲; 3、write(最后个数据包) -> end() 此时发磅缓冲有数据包,有FIN包,FIN包的被优先处理,导致后续的数据被丢弃;
翻了一遍unix网络编程,影响socket close行为的只有LINGER选项,但Node也没设置这个选项的方法,带外数据(优先级)也没讲到这种情况,有点懵懂。
有大神知道为什么么? 你的解答,我将万分感谢~