如何在套接字上使用Receive Async方法?

时间:2015-08-06 20:40:09

标签: c# .net sockets silverlight windows-phone-8.1

我正在尝试使用带有套接字的ReceiveAsync事件来读取数据。我可以成功地将数据发送到服务器,但是当服务器响应时,它不会显示在SocketAsyncEventArgs的缓冲区中。我使用Wireshark监控流量,我知道响应正在进行但我的应用程序没有注册它。

接收方法我做错了什么?

以下代码是我认为错误的地方。

buffer = new byte[4096];

SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.RemoteEndPoint = this._remoteEP;
args.UserToken = this._clientSocket;
args.SetBuffer(buffer, 0, buffer.Length);
this._clientSocket.ReceiveAsync(args);

byte[] udpMsg = new byte[buffer.Length];

Array.Copy(buffer, udpMsg, buffer.Length);

这是整个接收功能。

protected void ProcessReceivedMessages()
{
    byte[] buffer = null;
    int maxSize = AbstractNetworkUtils.GetMaxMessageSize();
    while (!this._isDone)
    {
        Thread.Sleep(1000);
        try
        {
            buffer = new byte[4096];

            SocketAsyncEventArgs args = new SocketAsyncEventArgs();
            args.RemoteEndPoint = this._remoteEP;
            args.UserToken = this._clientSocket;
            args.SetBuffer(buffer, 0, buffer.Length);
            this._clientSocket.ReceiveAsync(args);

            byte[] udpMsg = new byte[buffer.Length];

            Array.Copy(buffer, udpMsg, buffer.Length);  
            //buffer is a byte array of  size 4096 but it is always empty

            byte mType = AbstractCoAPMessage.PeekMessageType(udpMsg);

            if ( (mType == CoAPMessageType.CON ||
                        mType == CoAPMessageType.NON) && AbstractCoAPMessage.PeekIfMessageCodeIsRequestCode(udpMsg))
            {
                //This is a request
                CoAPRequest coapReq = new CoAPRequest();
                coapReq.FromByteStream(udpMsg);
                coapReq.RemoteSender = this._remoteEP;//Setup who sent this message
                string uriHost = ((IPEndPoint)this._remoteEP).Address.ToString();
                UInt16 uriPort = (UInt16)((IPEndPoint)this._remoteEP).Port;

                //setup the default values of host and port
                //setup the default values of host and port
                if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_HOST))
                        coapReq.Options.AddOption(CoAPHeaderOption.URI_HOST, AbstractByteUtils.StringToByteUTF8(uriHost));
                if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_PORT))
                    coapReq.Options.AddOption(CoAPHeaderOption.URI_PORT, AbstractByteUtils.GetBytes(uriPort));

                this.HandleRequestReceived(coapReq);
            }
            else
            {
                //This is a response
                CoAPResponse coapResp = new CoAPResponse();
                coapResp.FromByteStream(udpMsg);
                coapResp.RemoteSender = this._remoteEP;//Setup who sent this message
                //Remove the waiting confirmable message from the timeout queue
                if (coapResp.MessageType.Value == CoAPMessageType.ACK ||
                    coapResp.MessageType.Value == CoAPMessageType.RST)
                {
                    this._msgPendingAckQ.RemoveFromWaitQ(coapResp.ID.Value);
                }
            this.HandleResponseReceived(coapResp);
            }
        }
        catch (SocketException se)
        {
            //Close this client connection
            this._isDone = true;
            this.HandleError(se, null);
        }
        catch (ArgumentNullException argEx)
        {
            this.HandleError(argEx, null);
        }
        catch (ArgumentException argEx)
        {
            this.HandleError(argEx, null);
        }
        catch (CoAPFormatException fEx)
        {
            //Invalid message..
            this.HandleError(fEx, null);
        }                
    }
}

1 个答案:

答案 0 :(得分:0)

好的,我明白了。我为args.Completed添加了一个事件处理程序。

...
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.RemoteEndPoint = this._remoteEP;
args.SetBuffer(buffer, 0, buffer.Length);

args.Completed += new EventHandler<SocketAsyncEventArgs>(delegate (object s, SocketAsyncEventArgs e)
{
    if (e.SocketError == SocketError.Success)
    {
        byte[] udpMsg = new byte[e.BytesTransferred];
        // Retrieve the data from the buffer
        Array.Copy(e.Buffer, udpMsg, e.BytesTransferred);
        ...
    }
});
this._clientSocket.ReceiveAsync(args);
...

这是整个接收功能

protected void ProcessReceivedMessages()
{
    byte[] buffer = null;
    int maxSize = AbstractNetworkUtils.GetMaxMessageSize();
    while (!this._isDone)
    {
        Thread.Sleep(1000);
        try
        {
            buffer = new byte[maxSize * 2];

            SocketAsyncEventArgs args = new SocketAsyncEventArgs();
            args.RemoteEndPoint = this._remoteEP;
            args.SetBuffer(buffer, 0, buffer.Length);

            args.Completed += new EventHandler<SocketAsyncEventArgs>(delegate (object s, SocketAsyncEventArgs e)
            {
                if (e.SocketError == SocketError.Success)
                {
                    byte[] udpMsg = new byte[e.BytesTransferred];
                    // Retrieve the data from the buffer
                    Array.Copy(e.Buffer, udpMsg, e.BytesTransferred);

                    byte mType = AbstractCoAPMessage.PeekMessageType(udpMsg);

                    if ((mType == CoAPMessageType.CON ||
                            mType == CoAPMessageType.NON) && AbstractCoAPMessage.PeekIfMessageCodeIsRequestCode(udpMsg))
                    {
                        //This is a request
                        CoAPRequest coapReq = new CoAPRequest();
                        coapReq.FromByteStream(udpMsg);
                        coapReq.RemoteSender = this._remoteEP;//Setup who sent this message
                        string uriHost = ((IPEndPoint)this._remoteEP).Address.ToString();
                        UInt16 uriPort = (UInt16)((IPEndPoint)this._remoteEP).Port;

                        //setup the default values of host and port
                        //setup the default values of host and port
                        if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_HOST))
                            coapReq.Options.AddOption(CoAPHeaderOption.URI_HOST, AbstractByteUtils.StringToByteUTF8(uriHost));
                        if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_PORT))
                            coapReq.Options.AddOption(CoAPHeaderOption.URI_PORT, AbstractByteUtils.GetBytes(uriPort));

                        this.HandleRequestReceived(coapReq);
                    }
                    else
                    {
                        //This is a response
                        CoAPResponse coapResp = new CoAPResponse();
                        coapResp.FromByteStream(udpMsg);
                        coapResp.RemoteSender = this._remoteEP;//Setup who sent this message
                                                                //Remove the waiting confirmable message from the timeout queue
                        if (coapResp.MessageType.Value == CoAPMessageType.ACK ||
                        coapResp.MessageType.Value == CoAPMessageType.RST)
                        {
                            this._msgPendingAckQ.RemoveFromWaitQ(coapResp.ID.Value);
                        }
                        this.HandleResponseReceived(coapResp);
                    }
                }
            });
            this._clientSocket.ReceiveAsync(args);
        }
        catch (SocketException se)
        {
            //Close this client connection
            this._isDone = true;
            this.HandleError(se, null);
        }
        catch (ArgumentNullException argEx)
        {
            this.HandleError(argEx, null);
        }
        catch (ArgumentException argEx)
        {
            this.HandleError(argEx, null);
        }
        catch (CoAPFormatException fEx)
        {
            //Invalid message..
            this.HandleError(fEx, null);
        }
    }
}