简体   繁体   中英

Asynchronous TCP server/client unreliable packets?

Alright so for my game, Ive set up a server / client peer to peer connection, to send positions and etc back and forth.

Although my messages arent actually sending that fast, and not reliably either. As in parts of the strings are missing, and sometimes the sending just halts and the thread doesnt continue ( not sure why ).t

Anyways my Recieving code is here :

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


        }

    }

And my sending code here :

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

The packets are under the Encoding.ASCII.Getbytes.

And both the server and client are updating in while (true) threads with a Thread.Sleep(1).

Because you're trying to reconstitute a string bit by bit (this approach will break if you use more common multibyte encoding such as UTF8), your approach to this is fragile.

As stated in my comment, you might well miss your <eof> because it is split over two reads.

IMO, a preferable approach is to tag your message with a preceding length field (4 byte int) so that you don't have to tiptoe around at the end of the message trying to figure out if it's finished yet.

Just pour all your reads into a MemoryStream until you reach the indicated message length, then decode the contents of the MemoryStream with whatever encoding you see fit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM