8

私は本当に奇妙な問題を抱えており、それが私を夢中にさせています。

RubyサーバーとFlashクライアント(アクションスクリプト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()

DATAEOFnull charであるため、クライアントは文字列を解析します。

サーバーが新しいソケットを受け入れると、synctrue、autoflush、およびtrueに設定されますTCP_NODELAY

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

これは私の研究です:

情報:netstatデータを毎秒ファイルにダンプしていました。

  • クライアントがデータの受信を停止すると、netstatはソケットステータスがまだであることを示しますESTABLISHED
  • その数秒後、送信されたデータに応じてsend-queueが大きくなります。
  • tcpflowは、パケットが2回送信されることを示しています。
  • サーバーがソケットを閉じると、期待どおりにソケットのステータスがに変わりますFIN_WAIT1。次に、tcpflowは、バッファリングされたすべてのデータがクライアントに送信されているが、クライアントはデータを受信して​​いないことを示します。その数秒後、netstatから接続が失われ、tcpflowは同じデータが再度送信されたことを示しますが、今回はクライアントがデータを受信するため、サーバーへのデータの送信を開始し、サーバーがデータを受信します。しかし、手遅れです...サーバーが接続を閉じました。

スペインにあるVPSからアイルランドにあるAmazonEC2に変更したのですが、まだ問題が残っているため、OS/ネットワークの問題ではないと思います。

クライアントネットワークの問題でもないと思います。これは1日に数十回発生し、オンラインユーザーの平均数は約45〜55人で、1日あたりのユニークユーザー数は約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.

手順を実行しましたが、クライアントがインターネットへの接続を失った場合にのみ、サーバーが接続を閉じているようです。

これを答えとして追加して、人々がこれについて少しおかしなことを知っているようにします。

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.

手順を実行しましたが、クライアントがインターネットへの接続を失った場合にのみ、サーバーが接続を閉じているようです。

于 2012-10-10T14:48:42.997 に答える