簡體   English   中英

C# 套接字 ReceiveAsync

[英]C# Socket ReceiveAsync

我習慣於同步 sockets 並且有一些頭痛要達到我現在的地步,特別是Socket.Receive(..)並不總是接收所有字節

這是我以前使用的代碼

    public byte[] Receive(int size)
    {
        var buffer = new byte[size];
        var r = 0;
        do
        {
            // ReSharper disable once InconsistentlySynchronizedField
            var c = _clientSocket.Receive(buffer, r, size - r, SocketFlags.None);
            if (c == 0)
            {
                throw new SocketExtendedException();
            }
            r += c;
        } while (r != buffer.Length);
        return buffer;
    }

現在我開始在 Windows 電話中使用 sockets 但 .Receive .Receive(..)不可用,我設法讓Socket.ReceiveAsync(..)工作但我擔心(到目前為止沒有發生任何問題)這是我的新代碼,我尚未實現檢查是否已收到所有字節,我也不知道是否必須使用以下代碼

    private byte[] ReadBySize(int size = 4)
    {
        var readEvent = new AutoResetEvent(false);
        var buffer = new byte[size];
        var recieveArgs = new SocketAsyncEventArgs()
        {
            UserToken = readEvent
        };
        recieveArgs.SetBuffer(buffer, 0, size);
        recieveArgs.Completed += recieveArgs_Completed;
        _connecter.ReceiveAsync(recieveArgs);
        readEvent.WaitOne();

        if (recieveArgs.BytesTransferred == 0)
        {
            if (recieveArgs.SocketError != SocketError.Success)
                throw new SocketException((int)recieveArgs.SocketError);
            throw new CommunicationException();
        }
        return buffer;
    }

    void recieveArgs_Completed(object sender, SocketAsyncEventArgs e)
    {
        var are = (AutoResetEvent)e.UserToken;
        are.Set();
    }

這是我第一次使用ReceiveAsync ,有人可以指出我可能做錯的或需要更改的任何事情嗎

好吧,我去拿了一個大緩沖區並分批發送,中間有一個睡眠間隔以復制“並非所有字節都收到”所以我上面的代碼沒有收到所有字節。 對於那些也使用 ReceiveAsync(..) 的人,這是我有效的代碼

    private byte[] ReadBySize(int size = 4)
    {
        var readEvent = new AutoResetEvent(false);
        var buffer = new byte[size]; //Receive buffer
        var totalRecieved = 0;
        do
        {
            var recieveArgs = new SocketAsyncEventArgs()
            {
                UserToken = readEvent
            };
            recieveArgs.SetBuffer(buffer, totalRecieved, size - totalRecieved);//Receive bytes from x to total - x, x is the number of bytes already recieved
            recieveArgs.Completed += recieveArgs_Completed;
            _connecter.ReceiveAsync(recieveArgs);
            readEvent.WaitOne();//Wait for recieve

            if (recieveArgs.BytesTransferred == 0)//If now bytes are recieved then there is an error
            {
                if (recieveArgs.SocketError != SocketError.Success)
                    throw new ReadException(ReadExceptionCode.UnexpectedDisconnect,"Unexpected Disconnect");
                throw new ReadException(ReadExceptionCode.DisconnectGracefully);
            }
            totalRecieved += recieveArgs.BytesTransferred;

        } while (totalRecieved != size);//Check if all bytes has been received
        return buffer;
    }

    void recieveArgs_Completed(object sender, SocketAsyncEventArgs e)
    {
        var are = (AutoResetEvent)e.UserToken;
        are.Set();
    }

我使用 Socket 應用程序的方式是發送一個包含一些變量的 Buffer

[0] -> 0,1,2 0 is keep alive, 1 means there are data, 2 means a type off error occured
[1,2,3,4] size of the actual buffer I am sending
[x(size of 1,2,3,4)] the actual 'Serialized' data buffer

您可以創建一個套接字擴展,例如:

public static Task<int> ReceiveAsync(this Socket socket,
    byte[] buffer, int offset, int size, SocketFlags socketFlags)
{
    if (socket == null) throw new ArgumentNullException(nameof(socket));

    var tcs = new TaskCompletionSource<int>();
    socket.BeginReceive(buffer, offset, size, socketFlags, ar =>
    {
        try { tcs.TrySetResult(socket.EndReceive(ar)); }
        catch (Exception e) { tcs.TrySetException(e); }
    }, state: null);
    return tcs.Task;
}

然后是一種讀取所需大小的方法,如下所示:

public static async Task<byte[]> ReadFixed(Socket socket, int bufferSize)
{
    byte[] ret = new byte[bufferSize];
    for (int read = 0; read < bufferSize; read += await socket.ReceiveAsync(ret, read, ret.Length - read, SocketFlags.None)) ;
    return ret;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM