1

サーバー (c# を使用) とクライアント (フラッシュ、actionscript 3.0 を使用) アプリケーションを開発しています。サーバーはデータ (データは約 90 バイト) をクライアントに継続的に送信し、クライアントは受信したデータに従って動作します (データは json 形式です)。

しばらくの間、すべてが期待どおりに機能しますが、しばらくすると、クライアントは遅れてメッセージを受信し始めます。しばらく待機し続け、最後のメッセージに従って動作します (一部のメッセージが失われます)。しばらくすると、クライアントは待機を開始し、すべてのメッセージを同時に処理します。何が原因なのかわかりませんでした。ネットワークの状態は安定しています。

これが私のC#コードの一部で、メッセージを送信しています:

public void Send(byte[] buffer)
    {
        if (ClientSocket != null && ClientSocket.Connected)
        {
            ClientSocket.BeginSend(buffer, 0, buffer.Length, 0, WriteCallback, ClientSocket);
        }
    }

    private void WriteCallback(IAsyncResult result)
    {
        //
    }

クライアントの一部で、メッセージを受信して​​います (actionscript)

socket.addEventListener(ProgressEvent.SOCKET_DATA, onResponse);
function onResponse(e:ProgressEvent):void {
trace(socket.bytesAvailable);
if(socket.bytesAvailable > 0) {
    try
    {
        var serverResponse:String = socket.readUTFBytes(socket.bytesAvailable);

....

私の問題を説明できれば幸いです。コードを最適化するにはどうすればよいですか? ラグの原因となるもの。ありがとう。

4

1 に答える 1

2

ソケットをどのように設定しているかについて、より詳細な情報を提供する必要があります (それは TCP ですか、それとも UDP ですか?)。

それが TCP ソケットであると仮定すると、クライアントは、サーバーのSend()呼び出しによって送信されたのと同じバイト数を返す各受信呼び出しに依存しているように見えます。ただし、これは当てはまりません。メッセージがクライアントで部分的にしか受信されない場合、または複数のメッセージが一度に受信される場合は、問題の原因となる可能性があります。

たとえば、サーバーは 1 回の呼び出しで 90 バイトのメッセージを送信する場合がありますが、クライアントは 1 回の 90 バイトの受信、または 2 つの 45 バイトのチャンク、さらには 90 x 1 バイトのチャンク、またはその間の任意の受信で受信する場合があります。サーバーによって送信された複数のメッセージは、クライアントによって受信されるときに部分的に結合される場合もあります。たとえば、2 つの 90 バイトのメッセージが 1 つの 180 バイトのチャンク、または 150 バイトと 30 バイトのチャンクなどで受信される場合があります。

したがって、データのストリームがクライアントによって受信されたときに、個々のメッセージに確実に再構築できるように、メッセージに何らかのフレーミングを提供する必要があります。

最も基本的なフレーミング メカニズムは、送信される各メッセージの前に、メッセージ サイズを示す固定長フィールドを付けることです。メッセージの長さが 255 バイトを超えないことを保証できる場合は、1 バイトで済む可能性があります。これにより、受信コードが簡素化されます。

クライアント側では、最初に長さのプレフィックスを受け取り、ソケットからそのバイト数まで読み取ってメッセージ データを構築する必要があります。受信したバイト数が必要なバイト数よりも少ない場合、受信コードは、完全なメッセージが得られるまで、追加のデータを待機する必要があります (最終的に受信されたときに、部分的に受信されたメッセージに追加されます)。

完全なメッセージが受信されると、現在のように処理できます。

残念ながら私は ActionScript を知らないので、クライアント側のコードの例を示すことはできませんが、C# でサーバーとクライアントのフレーミングを記述する方法を次に示します。

サーバ側:

public void SendMessage(string message)
{
    var data = Encoding.UTF8.GetBytes(message);
    if (data.Length > byte.MaxValue) throw new Exception("Data exceeds maximum size");
    var bufferList = new[]
    {
        new ArraySegment<byte>(new[] {(byte) data.Length}),
        new ArraySegment<byte>(data)
    };
    ClientSocket.Send(bufferList);
}

クライアント側:

public string ReadMessage()
{
    var header = new byte[1];
    // Read the header indicating the data length
    var bytesRead = ServerSocket.Receive(header);
    if (bytesRead > 0)
    {
        var dataLength = header[0];
        // If the message size is zero, return an empty string
        if (dataLength == 0) return string.Empty;
        var buffer = new byte[dataLength];
        var position = 0;
        while ((bytesRead = ServerSocket.Receive(buffer, position, buffer.Length - position, SocketFlags.None)) > 0)
        {
            // Advance the position by the number of bytes read
            position += bytesRead;
            // If there's still more data to read before we have a full message, call Receive again
            if (position < buffer.Length) continue;
            // We have a complete message - return it.
            return Encoding.UTF8.GetString(buffer);
        }
    }
    // If Receive returns 0, the socket has been closed, so return null to indicate this.
    return null;
}
于 2012-06-13T02:24:09.567 に答える