8

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

我有一个 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);
}

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

sock.write(data + DATAEOF)
sock.flush()

DATAEOF是空字符,所以客户端解析字符串。

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

newsock = serverSocket.accept
newsock.sync = true
newsock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)

这是我的研究:

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

  • 当客户端停止接收数据时,netstat 显示套接字状态仍为ESTABLISHED.
  • 几秒钟后,发送队列会随着发送的数据而增长。
  • tcpflow 显示数据包被发送了 2 次。
  • 当服务器关闭套接字时,套接字状态按预期更改FIN_WAIT1为 。然后,tcpflow 显示所有缓冲的数据都发送到客户端,但客户端没有接收到数据。几秒钟后,netstat 的连接消失,tcpflow 显示再次发送相同的数据,但这次客户端接收到数据,因此开始向服务器发送数据,服务器接收到它。但是为时已晚...服务器已关闭连接。

我不认为这是操作系统/网络问题,因为我已经从位于西班牙的 VPS 更改为位于爱尔兰的 Amazon 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 的连接时才关闭连接。

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

4

1 回答 1

2

我认为答案是内核是关闭连接的那个。这是一些信息: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 的连接时才关闭连接。

于 2012-10-10T14:48:42.997 回答