1

さて、私のゲームでは、サーバー/クライアントのピアツーピア接続をセットアップし、位置などを前後に送信しました。

私のメッセージは実際にはそれほど速く送信されていませんが、信頼性も高くありません。文字列の一部が欠落しているため、送信が停止してスレッドが続行されないことがあります(理由は不明です)。

とにかく私の受信コードはここにあります:

    public void RecieveAsync()
    {

        if (netStream == null) netStream = Server.GetStream();


        if (netStream.DataAvailable == false) return;

        netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, new AsyncCallback(recieveCallBack), netStream);




    }


    public void recieveCallBack(IAsyncResult ar)
    {
        //try
        //{

        String content = String.Empty;

        Console.WriteLine("Stuck trying to get data");

        int rec = netStream.EndRead(ar);



        if (rec > 0)
        {


                Console.WriteLine(Encoding.ASCII.GetString(
    ReadBuffer, 0, rec));

            string packet = Encoding.ASCII.GetString(
    ReadBuffer, 0, rec);
                bool completedPacket = false;
                int appendTo = rec;

                if (packet.Contains("<eof>"))
                {
                    appendTo = packet.IndexOf("<eof>");
                    packet.Replace("<eof>", "");
                    completedPacket = true;
                }

                SB.Append(packet, 0, appendTo);

                // Check for end-of-file tag. If it is not there, read   
                // more data.  

                content = SB.ToString();



            if (completedPacket)
            {
                // All the data has been read from the   
                // client. Display it on the console.  


                if (DataRecieved != null)
                {
                    string RecievedData = SB.ToString();

                    DataRecieved(RecievedData);

                    netStream.Flush();

                    Array.Clear(ReadBuffer, 0, ReadBuffer.Length);
                    ReadBuffer = new byte[1024];
                }

                SB.Clear();

                // Echo the data back to the client.  
            }
            else
            {
                // Not all data received. Get more.  
                Array.Clear(ReadBuffer, 0, ReadBuffer.Length);
                ReadBuffer = new byte[1024];
                netStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, recieveCallBack, netStream);
            }


        }

    }

そして、ここに私の送信コード:

    public void Send(byte[] data, int index, int length)
    {
        //add data as state

        //socket.NoDelay = true;

        if (netStream == null) netStream = TcpClient.GetStream();

        netStream.BeginWrite(data, 0, length, sendCallback, netStream);




    }

    private void sendCallback(IAsyncResult ar)
    {
        //try
        //{
           netStream.EndWrite(ar);

            //if (ar.AsyncState != null)
            //{
            //    byte[] buffer = (byte[])ar.AsyncState;
            //    socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, sendCallback, null);
            //    return;
            //}

            if (OnSend != null)
            {
                OnSend(this);
            }

            netStream.Flush();


        //catch (Exception ex)
        //{
        //    System.Windows.Forms.MessageBox.Show(ex.ToString());
        //    return;
        //}
    }

パケットは Encoding.ASCII.Getbytes の下にあります。

また、サーバーとクライアントの両方が、Thread.Sleep(1) を使用して while (true) スレッドで更新しています。

4

1 に答える 1

0

文字列を少しずつ再構成しようとしているため (UTF8 などのより一般的なマルチバイト エンコーディングを使用すると、このアプローチは機能しなくなります)、これに対するアプローチは脆弱です。

<eof>私のコメントで述べたように、 2 つの読み取りに分割されているため、見逃す可能性があります。

IMO、望ましいアプローチは、メッセージの最後にまだ終了しているかどうかを把握しようとしてつま先立ちする必要がないように、メッセージに先行する長さフィールド (4 バイトの int) をタグ付けすることです。

MemoryStream指定されたメッセージ長に達するまで、すべての読み取りを a に注ぎ込み、MemoryStream適切と思われるエンコーディングで の内容をデコードします。

于 2013-01-24T10:26:29.360 に答える