ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C#中的异步套接字

2019-12-10 06:07:09  阅读:398  来源: 互联网

标签:sockets asynchronous c


我对在C#中使用异步套接字方法的正确方法感到困惑.我将参考这两篇文章来解释问题并提出我的问题:MSDN article on asynchronous client socketsdevarticles.com article on socket programming.

我的问题是关于BeginReceive()方法. MSDN文章使用以下两个功能来处理接收数据:

private static void Receive(Socket client) 
{
  try 
  {
    // Create the state object.
    StateObject state = new StateObject();
    state.workSocket = client;

    // Begin receiving the data from the remote device.
    client.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
        new AsyncCallback(ReceiveCallback), state);
  } 
  catch (Exception e) 
  {
    Console.WriteLine(e.ToString());
  }
}

private static void ReceiveCallback( IAsyncResult ar ) 
{
  try 
  {
     // Retrieve the state object and the client socket 
     // from the asynchronous state object.
     StateObject state = (StateObject) ar.AsyncState;
     Socket client = state.workSocket;
     // Read data from the remote device.
     int bytesRead = client.EndReceive(ar);
     if (bytesRead > 0) 
     {
         // There might be more data, so store the data received so far.
        state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
         //  Get the rest of the data.
        client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
            new AsyncCallback(ReceiveCallback), state);
     } 
     else 
     {
        // All the data has arrived; put it in response.
       if (state.sb.Length > 1) 
       {
         response = state.sb.ToString();
       }
       // Signal that all bytes have been received.
       receiveDone.Set();
     }
   } 
   catch (Exception e) 
   {
     Console.WriteLine(e.ToString());
   }
 }

尽管devarticles.com教程为BeginReceive方法的最后一个参数传递了null,然后继续说明了当我们处理多个套接字时,最后一个参数很有用.现在我的问题是:

>如果仅使用单个套接字,将状态传递给BeginReceive方法有什么意义?是否要避免使用类字段?这样做似乎没有什么意义,但是也许我错过了一些东西.
>当处理多个套接字时,状态参数如何提供帮助?如果我正在调用client.BeginReceive(…),是否会从客户端套接字读取所有数据? devarticles.com教程使其听起来像这样:
m_asynResult = m_socClient.BeginReceive(theSocPkt.dataBuffer,0,theSocPkt.dataBuffer.Length,SocketFlags.None,pfnCallBack,theSocPkt);

数据将从theSocPkt.thisSocket套接字读取,而不是从m_socClient套接字读取.在他们的示例中,两者是相同的,但是如果不是这样会发生什么呢?

我只是没有真正看到最后一个参数在什么地方有用,或者至少对于多个​​套接字有什么帮助.如果我有多个套接字,我仍然需要在每个套接字上调用BeginReceive,对吗?

解决方法:

What is the point of passing a state to the BeginReceive method if we’re only working with a single socket? Is it to avoid using a class field? It seems like there’s little point in doing it, but maybe I’m missing something.

没错,如果您不使用状态,则必须使用成员.但这比状态变量少局部.本地内容越多,在代码的其他部分进行更改时,它们破坏的可能性就越小.

将其与普通方法调用进行比较.为什么我们不只是将参数设置为成员,然后在不带任何参数的情况下调用所有函数?它可以工作…但是阅读代码太可怕了.通过使范围尽可能地局部化,可以使设计更易于理解和修改.改进的封装导致更强大的代码.

此处同样适用.如果您只有一个异步回调,则可以只在类上设置一个成员就可以摆脱困境,但是如果您有很多此类调用,则此策略将很快导致如上所述的类似问题-令人困惑和脆弱的代码.

How can the state parameter help when dealing with multiple sockets?

您可以为每个调用传递一个不同的状态对象,每个对象都包含自己的客户端对象.请注意,客户端是从状态而不是从成员变量中获取的:

//Socket client = this.client; // Don't do this.
Socket client = state.workSocket; 

如果您注意到MSDN文档中的所有其他方法,请将“客户端”作为参数.状态是传递参数的一种方式,因为方法签名是固定的.

更新:关于注释中的问题,.NET检查您是否使用了正确的客户端对象,如果没有,则抛出ArgumentException.通过在.NET Reflector中反编译EndReceive,我们可以看到:

if ((result == null) || (result.AsyncObject != this))
{
    throw new ArgumentException(SR.GetString("net_io_invalidasyncresult"), "asyncResult");
}

标签:sockets,asynchronous,c
来源: https://codeday.me/bug/20191210/2099731.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有