Socket.BeginReceive():如何处理“ReceiveCallback”上的大端数据?

问题描述 投票:0回答:1

以下代码(this示例中的镜像)似乎可以很好地接收小端数据(已测试),但我需要接收大端数据(来自Android手机)并且任何尝试恢复字节都会导致反转字节数据末尾有一个奇怪的字符(见下图)。是的,我正在从 Android 代码发送 UTF8 字节。

IMAGE

我正在使用 this 代码的异步版本(请参阅客户端部分),它可以很好地接收 bin 数据和文本,因为您在第一次迭代后恢复字节顺序。

这是有问题的代码:

`class Client
{
    public Socket socket;
    public Guid ID;
    public string RemoteAddress;
    public byte[] Buffer = new byte[1024];
    public int DataSize = 0;
    public int PrefixSize = 0;
    public uint tickCount = 0;
    public bool DataSizeReceived = false;
    public bool lengthRead = false;
    public MemoryStream Data = new MemoryStream();

    public Client(Socket socket)
    {
        this.socket = socket;
        ID = Guid.NewGuid();
        RemoteAddress = socket.RemoteEndPoint.ToString();
    }
}

private bool _IsConnected(Socket socket)
{
    try
    {
        return !(socket.Poll(1000, SelectMode.SelectRead) && socket.Available == 0);
    }
    catch (SocketException)
    {
        return false;
    }
}

private void ReceiveCallback(IAsyncResult ar)
{
    int dataOffset = 0;
    int restOfData = 0;
    int dataRead = 0;
    Boolean StreamClosed = false;
    long cDataLength = 0;
    long LastiDataLength = 0;

    SocketError socketError = SocketError.TypeNotFound;

    Client c = (Client)ar.AsyncState;

    if (!c.socket.Connected)
    {
        // Not Connected anymore ?
        return;
    }

    try
    {
        dataRead = c.socket.EndReceive(ar, out socketError);
    }
    catch (Exception)
    {
       // Your code goes here..
    }

    if (socketError != SocketError.Success)
    {
        // Has Connection been lost ?
        OnConnectionDropped(client);
        return;
    }

    if (dataRead <= 0)
    {
       // Has connection been lost ?
        OnConnectionDropped(client);
        return;
    }
    
    while (dataRead > 0)
    {
        if (!c.DataSizeReceived)
        {
            if (!c.lengthRead)
            {
                c.PrefixSize = dataRead;
                Array.Resize(ref c.Buffer, c.PrefixSize);
                Array.Reverse(c.Buffer);
                c.lengthRead = true;
            }

            if (c.Data.Length > 0)
            {
                restOfData = c.PrefixSize - (int)c.Data.Length;
                c.Data.Write(c.Buffer, dataOffset, restOfData);
                dataRead -= restOfData;
                dataOffset += restOfData;
            }
            else if (dataRead >= c.PrefixSize)
            {
                c.Data.Write(c.Buffer, dataOffset, c.PrefixSize);
                dataRead -= c.PrefixSize;
                dataOffset += c.PrefixSize;
                c.lengthRead = false;

                // Handle the received messsage

               string text = Encoding.UTF8.GetString(c.Data.GetBuffer(), 0, (int)c.Data.Length);
               MessageBox.Show(text);
                
               // ============================
            }
            else
            {
                c.Data.Write(c.Buffer, dataOffset, dataRead);
                dataOffset += dataRead;
                dataRead = 0;
            }

            if (c.Data.Length == c.PrefixSize)
            {
                c.DataSize = BitConverter.ToInt32(c.Data.GetBuffer(), 0);
                c.DataSizeReceived = true;
                c.Data.Position = 0;
                c.Data.SetLength(0);
                c.lengthRead = false;
            }
            else
            {
                c.socket.BeginReceive(c.Buffer, 0, c.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), c);
                return;
            }
        }

        try
        {
            cDataLength = c.Data.Length;
            LastiDataLength = cDataLength;
        }
        catch (ObjectDisposedException)
        {
            StreamClosed = true;
        }
        if (!StreamClosed)
        {
            if ((cDataLength + dataRead) >= c.DataSize)
            {
                restOfData = c.DataSize - (int)c.Data.Length;

                c.Data.Write(c.Buffer, dataOffset, restOfData);

                // Handle the received messsage

               string text = Encoding.UTF8.GetString(c.Data.GetBuffer(), 0, (int)c.Data.Length);
               MessageBox.Show(text);
                
               // ============================

                dataOffset += restOfData;
                dataRead -= restOfData;

                c.Data = new MemoryStream();
                c.Data.Position = 0;
                c.DataSizeReceived = false;
                c.DataSize = 0;

                if (dataRead == 0)
                {
                    if (_IsConnected(c.socket))
                    {
                        c.socket.BeginReceive(c.Buffer, 0, c.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), c);
                        return;
                    }
                }
                else
                    continue;
            }
            else
            {
                if (_IsConnected(c.socket))
                {
                    c.Data.Write(c.Buffer, dataOffset, dataRead);

                    c.socket.BeginReceive(c.Buffer, 0, c.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), c);

                    dataRead = 0;
                }
            }
        }
        else
        {
            if (LastiDataLength + dataRead == c.DataSize)
            {
                if (_IsConnected(c.socket))
                {
                    c.socket.BeginReceive(c.Buffer, 0, c.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), c);
                }
                return;
            }
            else
            {

            }
        }

        if (!_IsConnected(c.socket))
            dataRead = -1;
    }
}`
c# sockets network-programming endianness
1个回答
0
投票

好吧,我没有正确获取消息的大小。下面是解决办法:

if (!c.lengthRead)
{
    byte[] BodyLengthR = new byte[4];
    Array.Copy(c.Buffer, BodyLengthR, 4);
    Int32 Endian = BitConverter.ToInt32(BodyLengthR, 0);
    BodySize = IPAddress.NetworkToHostOrder(Endian);

    c.PrefixSize = BodySize + 4;
    Array.Resize(ref c.Buffer, c.PrefixSize);
    c.lengthRead = true;
}
© www.soinside.com 2019 - 2024. All rights reserved.