.NET中的异步TCP通信

时间:2009-02-20 22:22:45

标签: .net networking sockets asynchronous tcp

这里的快速问题:使用与NetworkStream类(由TcpClient生成)的异步通信,即BeginRead / BeginWrite方法,而不是运行单独的线程并对其使用同步操作,即读/写,是否有任何明显的好处?我的印象是(很可能是非常错误的)异步操作是非阻塞的并且在OS级别(在TCP堆栈中执行?)执行,并带有回调的线程池项。我认为它肯定必须与在同步方法上调用ThreadPool.QueueUserWorkItem不同,或者提供它时没有什么意义。现在,我相信这至少是文件I / O所发生的事情(操作系统级调用),但如果有人可以澄清有关网络(TCP)通信的问题,那将是最有帮助的。基本上,我想知道这两种方法是否有任何特定的好处(除了能够在同步调用中使用BinaryReader / StreamReader类的明显优势)。

4 个答案:

答案 0 :(得分:10)

有一点不同,如果你使用一个Worker线程调用同步版本,你将在阻塞调用中占用一个线程。

尽管Begin方法不会占用一个线程,但会在适当的I / O信号上使用回调,然后回调将在池中的一个线程上运行。

答案 1 :(得分:1)

正如其他人所指出的那样,当您使用同步方法增加同时连接数时,为您的进程分配另一个线程会对您产生影响。

但是,如果你知道你只会有少量的连接,我会说它变成了一种清洗,你应该选择最适合你应用的方法。

在线程开销可以忽略不计的情况下,我希望这两个场景能够像这样发挥。

<强>异步:

  1. 您调用BeginRead / BeginWrite
  2. “系统”(框架/ OS)被告知您想要什么
  3. 读/写完成
  4. “系统”告诉线程池中的线程调用您的回调
  5. 您可以做任何您需要做的事情来完成操作
  6. 在另一个主题中同步:

    1. 您从线程池中获取一个线程来处理IO
    2. 您打电话给读/写
    3. “系统”(框架/ OS)被告知您想要什么
    4. 读/写完成
    5. 您可以做任何您需要做的事情来完成操作
    6. 这里唯一的区别是异步调用的第4步成为另一个线程案例中同步的第1步。

答案 2 :(得分:1)

我同意AnthonyWJones,想象你的线程池有10个线程,但你有100个被动的enought客户端。使用异步调用,您可以为每一个调用BeginRead,并且当某个数据准备就绪时,它将由其中一个池线程处理。但是,如果您尝试使用QueueUserWorkItem,则只会安排从10个客户端接收数据。如果他们在1小时内没有发送任何内容,其他90个客户将永远无法获得数据。

答案 3 :(得分:1)

我不确定为什么NetworkStream甚至有一个BeginRead / Write,因为这基本上违反了NetworkStream的目的。通过使用Async方法,您可以获得更快的响应,更高的可伸缩性和更少的资源消耗。

如果你一次只有一个连接,那么如果你使用一个线程池线程没关系,但如果你接受了很多连接,那么你肯定想要使用异步。