.net NET中的异步TCP通信

.net NET中的异步TCP通信,.net,networking,sockets,asynchronous,tcp,.net,Networking,Sockets,Asynchronous,Tcp,这里有一个快速问题:与NetworkStream类(由TcpClient生成)使用异步通信,即BeginRead/BeginWrite方法,而不是运行单独的线程并在其上使用同步操作,即读/写,有什么明显的好处吗?我的印象是(这很容易是错误的)异步操作是非阻塞的,并且在操作系统级别执行(可能在TCP堆栈中?),回调使用线程池项。我认为它肯定不同于在同步方法上调用ThreadPool.QueueUserWorkItem,否则提供它就没有什么意义了。现在,我很有信心,至少在文件I/O中会发生这样的事情

这里有一个快速问题:与NetworkStream类(由TcpClient生成)使用异步通信,即BeginRead/BeginWrite方法,而不是运行单独的线程并在其上使用同步操作,即读/写,有什么明显的好处吗?我的印象是(这很容易是错误的)异步操作是非阻塞的,并且在操作系统级别执行(可能在TCP堆栈中?),回调使用线程池项。我认为它肯定不同于在同步方法上调用ThreadPool.QueueUserWorkItem,否则提供它就没有什么意义了。现在,我很有信心,至少在文件I/O中会发生这样的事情(操作系统级调用),但如果有人能澄清有关网络(TCP)通信的问题,那将是非常有帮助的。基本上,我想知道这两种方法是否有任何特殊的好处(除了能够将BinaryReader/StreamReader类与同步调用一起使用这一明显的好处),当您使用同步方法增加同时连接的数量时,将另一个线程分配给您的进程将对您产生影响

然而,如果你知道你将只有一小部分的连接,我会说这将成为一个清洗,你应该选择最适合你的应用程序的方法

在线程开销可以忽略不计的情况下,我希望这两种情况都是这样

异步:

  • 你打电话给Beginhead/BeginWrite
  • “系统”(框架/操作系统)被告知您想要什么
  • 读/写操作完成
  • “系统”告诉线程池中的线程调用回调
  • 你做任何你需要做的事情来完成手术
  • 在另一个线程中同步:

  • 您可以从线程池中获得一个线程来处理IO
  • 你打电话读/写
  • “系统”(框架/操作系统)被告知您想要什么
  • 读/写操作完成
  • 你做任何你需要做的事情来完成手术

  • 这里唯一的区别是,异步调用的步骤4在另一个线程情况下成为同步调用的步骤1。

    有一个区别,如果您使用工作线程调用同步版本,您将在阻塞调用中绑定其中一个线程


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

    我同意AnthonyWJones的观点,假设您的线程池有10个线程,但您有100个被动enough客户端。通过异步调用,您可以从它们中的每一个开始,当来自某个线程的数据准备就绪时,它将由其中一个池线程处理。但如果您尝试使用QueueUserWorkItem,您将只安排从10个客户端接收数据。如果他们在1小时内什么也不发送,那么其他90个客户端将永远没有机会获取数据。

    我真的不确定NetworkStream为什么会有一个起始/写入,因为这首先基本上违背了NetworkStream的目的。通过使用异步方法,您可以获得更快的响应、更大的可扩展性和更少的资源消耗


    如果您一次只能有一个连接,那么您是否使用线程池线程并不重要,但是如果您接受多个连接,那么您肯定希望使用异步。

    对,这正是我所怀疑的。因此,您建议在可能的情况下,在单独的线程上使用Begin方法而不是同步方法?这样做似乎更优雅,如果不是更高效的话。.低级别(BeingXX/EndXX)模式的NET framework实现通常使用IO完成端口。这是Windows下可用的最具可扩展性的IO方法。@Noldorin:是的,我建议使用Begin方法,主要是因为这样代码更简单,幸好在这种情况下,更简单的方法也更有效。@Richard:很高兴得到一些确认,干杯@非常感谢,答案是你的。是的,这基本上是我的另一个考虑。Hrmm,现在我有两个相反的观点,我开始时也是这样……一个线程,即使被阻塞,也是一个重要的资源(从进程的VM空间分配的1MB堆栈空间开始)。我在一定程度上同意这一点,但因为我们在这里谈论从池中获取线程,我不知道这有多重要。除非我能证明自己有问题,否则我倾向于做对申请最自然的事情。过早的优化和所有…不同之处在于可伸缩性。对于一个连接来说没有太大的区别,对于100个连接来说有。当处理10000个连接时,同步方法根本不起作用。而且操作系统有很多“特殊魔力”,这意味着异步版本非常高效。这将是一个可证明的问题。我想我们在这里都同意:-)事实上,我看到调用Begin方法显然不等同于现在的QueueUserItmem。。。不过,最主要的一点是它与运行带有同步操作的独立线程的比较。如果您显式使用池中的线程或自己创建多个线程,则没有太大区别-无论您的线程数量如何有限。。。使用异步操作时,线程仅用于执行实际作业,然后释放。使用同步操作,线程可能会被空闲等待阻塞。我明白你的意思。这些异步方法可能更适合TcpClient类内部。似乎大家的共识是稍微倾向于使用异步方法来获得更好的性能(如果只是略微)。