0

C# を使用してクライアント サーバー アプリケーションを作成しました。

クライアントはメッセージ サイズを定義する 4 バイトのヘッダーを含むメッセージを非同期的に送信し、サーバーはメッセージ全体を待機して(サイズを認識)、DataReceivedイベントを発生させます。データを非同期で送受信すると、これはすべて正常に機能します。

ある時点で、接続不良をシミュレートしたいと考えていました。この接続では、2 つのセグメントが次から次へと送信されましたSend()BeginSend()

  public void SendSyncString(string str, Commands cmd)
    {

        BinaryWriter bw = new BinaryWriter(new MemoryStream());
        bw.Write((int)cmd);
        bw.Write((int)str.Length);
        bw.Write(Encoding.ASCII.GetBytes(str));
        bw.Close();
        byte[] data = ((MemoryStream)(bw.BaseStream)).ToArray();
        bw.BaseStream.Dispose();
        SendSync(data,1);

    }

    public void SendSync(byte[] data,int delay)
    {
        //create |dataLength|data| segment
        byte[] dataWithHeader = Combine(BitConverter.GetBytes(data.Length), data);
        //send first block of data, delay, and then send the rest
        socket.Send(dataWithHeader, 0, 4, SocketFlags.None);
        Thread.Sleep(delay*1000);
        socket.Send(dataWithHeader, 5, dataWithHeader.Length - 5, SocketFlags.None);
    }

これはうまくいきません。しかし、その理由を理解したいと思います。TCP が単なるバイト ストリームであり、各セグメントがいつ到着するかを知る方法がない場合、必要に応じてセグメントに分割し、上記のように単純に送信できないのはなぜですか (最初の 4 バイトが完全に送信されました)?

洞察をありがとう。

4

2 に答える 2

4

最初の socket.Send 呼び出しは 4 バイトしか送信しなかったため:

socket.Send(dataWithHeader, 0, 4, SocketFlags.None);

つまり、オフセット 0、1、2、および 3 のバイトが送信されます (合計 4 バイト)。socket.Send の 3 番目のパラメーターを思い出してください。Send は長さパラメーターであり、終了位置ではありません。

したがって、この行にはバグがあります。

socket.Send(dataWithHeader, 5, dataWithHeader.Length - 5, SocketFlags.None);

オフセット 5,6,7.. から配列の最後までバイトを送信します。バイト 4 をスキップしました。 したがって、完全なメッセージを受信するには 1 バイト足りないため、受信者はブロックする可能性があります。

それは読むべきです:

socket.Send(dataWithHeader, 4, dataWithHeader.Length - 4, SocketFlags.None);

ほらね。

于 2013-03-07T08:31:26.210 に答える
1

2 つのセグメントが次々に送信される、接続不良をシミュレートしたかった

それは「悪い接続」ではありません。これは、TCP 接続が動作するための完全に合法的な方法です。受信側のソフトウェアがそれに対応していない場合は、正しく記述されていません。

最初の 4 バイトが完全に送信されたと仮定します。

あなたはそれを仮定することはできません。

于 2013-03-07T10:13:28.497 に答える