C# 异步TCP服务器/客户端不可靠数据包?

C# 异步TCP服务器/客户端不可靠数据包?,c#,asynchronous,tcp,tcpclient,netstream,C#,Asynchronous,Tcp,Tcpclient,Netstream,好的,对于我的游戏,我建立了一个服务器/客户端点对点连接,来回发送位置等 虽然我的信息实际上发送得并不那么快,也不可靠。正如中所述,部分字符串丢失,有时发送只是暂停,线程无法继续(不确定原因)。t 无论如何,我的接收代码如下: public void RecieveAsync() { if (netStream == null) netStream = Server.GetStream(); if (netStream.DataAvailab

好的,对于我的游戏,我建立了一个服务器/客户端点对点连接,来回发送位置等

虽然我的信息实际上发送得并不那么快,也不可靠。正如中所述,部分字符串丢失,有时发送只是暂停,线程无法继续(不确定原因)。t

无论如何,我的接收代码如下:

    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);
            }


        }

    }
数据包在Encoding.ASCII.Getbytes下


服务器和客户机都在使用Thread.Sleep(1)更新while(true)线程

因为您试图一点一点地重新构造字符串(如果您使用更常见的多字节编码,如UTF8,这种方法将失效),所以您的方法很脆弱

正如我在评论中所说的,您可能会错过您的
,因为它分为两次读取

在我看来,一种更好的方法是使用前面的长度字段(4字节int)标记消息,这样您就不必在消息结束时踮着脚尖想知道消息是否完成了


只需将所有读取内容倒入
MemoryStream
中,直到达到指定的消息长度,然后使用您认为合适的任何编码对
MemoryStream
的内容进行解码。

同样,如果在读取之间进行拆分,则会显示数据包的结尾吗?在我看来,一旦发送,您也会合并数据包,以及移除框架(该
DataReceived
可能会得到不止一个“数据包”(用您的术语,而不是底层网络术语),并且无法解读它。从根本上说,这里要做的事情是记录你正在接收的所有信息,以及你正在处理的所有信息,这样你就可以看到哪里出了问题。标记我的消息是什么意思?就像在它前面发送一个表示长度的数据包一样?@user1965626:是的,就是那个。。。一个4字节的“数据包”,表示长度,因此一次读取由1个字节组成。读取几个表示长度的字节(如果是int,则可能为4)2。读取
length
字节以获取消息
    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;
        //}
    }