0

クラスを使用System.Net.Socketsして C# でゲームのネットワーク部分を記述しようとしています。TcpClient

  • 各更新サーバーはクライアントに情報を送信しています。
  • すべての情報は 2kb のパケットに組み込まれているため、1 回の更新で 1-2-3-5-10 パケットを送信できます。
  • クライアントは情報をチェックしており、情報が正しい形式である場合は、それを読み取ります。
  • サーバーがあまりにも多くのパケットを送信しようとし始めるまで、すべてが正常に機能しています。
  • クライアントがときどき間違ったデータを含むパケットを受信することがある場合、通常は 20 ~ 50 パケットの 1 つです。
  • たとえば、通常、1 回の更新で 1 ~ 2 パケットは正常に受信されますが、更新で 3 ~ 10 個のパケットを受信すると、間違ったデータ ストリームが返されます。
  • 一度に複数のクライアントを起動している場合、サーバーから同じデータ ストリームを取得する必要があります。異なる数の成功データ ストリームと失敗データ ストリームが取得されます。

この間違ったデータ ストリームを回避するにはどうすればよいですか?

1 ミリ秒で送信するデータが多すぎて、時間をかけて送信する必要がありますか?

これは送信情報です:

TcpClient client;

public void SendData(byte[] b)
    {
        //Try to send the data.  If an exception is thrown, disconnect the client
        try
        {
            lock (client.GetStream())
            {
                client.GetStream().BeginWrite(b, 0, b.Length, null, null);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

これは受信情報です。

byte[] readBuffer;
int byfferSize = 2048;

private void StartListening()
    {
        client.GetStream().BeginRead(readBuffer, 0, bufferSize, StreamReceived, null);
    }

    private void StreamReceived(IAsyncResult ar)
    {
        int bytesRead = 0;
        try
        {
            lock (client.GetStream())
            {
                bytesRead = client.GetStream().EndRead(ar); // просмотр длины сообщения
            }
        }
        catch (Exception ex)
        { MessageBox.Show(ex.Message); }

        //An error happened that created bad data
        if (bytesRead == 0)
        {
            Disconnect();
            return;
        }

        //Create the byte array with the number of bytes read
        byte[] data = new byte[bytesRead];

        //Populate the array
        for (int i = 0; i < bytesRead; i++)
            data[i] = readBuffer[i];

        //Listen for new data
        StartListening();

        //Call all delegates
        if (DataReceived != null)
            DataReceived(this, data);
    }

メインネットワークコードです。

4

1 に答える 1

2

データを受け取った後にそのデータをどうするかはわかりませんが、接続からすべてのデータを読み取っていない可能性は十分にあります。あなたが持っている:

bytesRead = client.GetStream().EndRead(ar);

読み取ったバイト数が、サーバーが送信したすべてのバイトであるという保証はありません。たとえば、サーバーは 2,048 バイトを送信した可能性がありますが、 を呼び出したときはRead1,024 バイトしか使用できませんでした。残りはまだ「輸送中」です。NetworkStream.Readのドキュメントには次のように書かれています。

Read 操作は、size パラメーターで指定されたバイト数まで、使用可能なデータをすべて読み取ります。

部分的なパケットを取得している可能性があります。ハンドラーがバッファーに完全なパケットが含まれているDataReceivedと想定すると、問題が発生します。data

ネットワーク ストリームから確実に読み取るには、読み取るデータの量を把握するか、レコード セパレータが必要です。完全なパケットを期待している場合は、処理を試みる前に、完全なパケットを取得することを確認する必要があります。コードbytesReadは 0 でないかどうかを確認するだけです。それ以外の場合は、それを渡します。DataReceivedハンドラーが部分的なパケットをバッファリングする方法を知らない限り、これは問題になります。

別の注意として、ネットワーク ストリームをロックする必要はありません。複数のスレッドが同じストリームから読み取ることができない場合を除きます。そして、それは悲惨なことになるでしょう。ロックをはずします。あなたはそれを必要としません。

于 2013-07-25T16:41:57.627 に答える