TCP套接字在关闭之前停止接收数据

Jor*_*lez 8 ruby flash networking tcp actionscript-3

我有一个非常奇怪的问题让我发疯.

我有一个Ruby服务器和一个Flash客户端(Action Script 3).这是一款多人游戏.

问题是一切都工作正常,然后突然间,随机播放器停止接收数据.当服务器由于不活动而关闭连接时,大约20-60秒后,客户端会收到所有缓冲的数据.

客户端XMLsocket用于检索数据,因此客户端接收数据的方式不是问题.

socket.addEventListener(Event.CONNECT, connectHandler);
function connectHandler(event)
{
    sendData(sess);
}

function sendData(dat)
{
    trace("SEND: " + dat);
    addDebugData("SEND: " + dat)
    if (socket.connected) {
        socket.send(dat);
    } else {
        addDebugData("SOCKET NOT CONNECTED")
    }
}

socket.addEventListener(DataEvent.DATA, dataHandler);
function dataHandler(e:DataEvent) {
    var data:String = e.data;
    workData(data);
}
Run Code Online (Sandbox Code Playgroud)

服务器在每次写入后刷新数据,因此不是刷新问题:

sock.write(data + DATAEOF)
sock.flush()
Run Code Online (Sandbox Code Playgroud)

DATAEOF 是null char,因此客户端解析字符串.

当服务器接受新套接字时,它设置sync为true,autoflush和TCP_NODELAYtrue:

newsock = serverSocket.accept
newsock.sync = true
newsock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
Run Code Online (Sandbox Code Playgroud)

这是我的研究:

信息:我每秒都会将netstat数据转储到一个文件中.

  • 当客户端停止接收数据时,netstat会显示套接字状态仍然存在ESTABLISHED.
  • 几秒钟后,send-queue会相应地增加发送的数据.
  • tcpflow显示数据包被发送2次.
  • 当服务器关闭套接字时,套接字状态将更改为FIN_WAIT1,如预期的那样.然后,tcpflow显示所有缓冲的数据都发送到客户端,但客户端不接收数据.几秒钟之后,来自netstat和tcpflow的连接消息显示再次发送相同的数据,但这次客户端接收数据,因此开始向服务器发送数据,服务器接收数据.但为时已晚......服务器已关闭连接.

我不认为这是一个操作系统/网络问题,因为我已经从位于西班牙的VPS改为位于爱尔兰的亚马逊EC2,问题仍然存在.

我不认为这也是一个客户端网络问题,因为这种情况每天发生几十次,在线用户的平均数量约为45-55,每天约有400个独立用户,因此这个比例非常高.

编辑: 我做了更多的研究.我已经将服务器更改为C++.

当客户端停止发送数据时,服务器会在一段时间后收到"按对等方重置连接"错误.在那一刻,tcpdump告诉我客户端发送了一个RST数据包,这可能是因为客户端关闭了连接并且服务器试图读取,但是......为什么客户端关闭连接?我认为答案是客户端不是关闭连接的客户端,而是内核.以下是一些信息:http://scie.nti.st/2008/3/14/amazon-s3-and-connection-reset-by-peer

Basically, as I understand it, Linux kernels 2.6.17+ increased the maximum size of the TCP window/buffer, and this started to cause other gear to wig out, if it couldn’t handle sufficiently large TCP windows. The gear would reset the connection, and we see this as a “Connection reset by peer” message.

我按照这些步骤进行操作,现在似乎只有在客户端丢失与Internet的连接时,服务器才会关闭连接.

我要将此作为答案添加,以便人们对此有所了解.

Jor*_*lez 2

我认为答案是内核是关闭连接的。以下是一些信息:http://scie.nti.st/2008/3/14/amazon-s3-and-connection-reset-by-peer

\n\n

Basically, as I understand it, Linux kernels 2.6.17+ increased the maximum size of the TCP window/buffer, and this started to cause other gear to wig out, if it couldn\xe2\x80\x99t handle sufficiently large TCP windows. The gear would reset the connection, and we see this as a \xe2\x80\x9cConnection reset by peer\xe2\x80\x9d message.

\n\n

我已按照步骤操作,现在看来服务器仅在客户端失去与互联网的连接时才会关闭连接。

\n