我应该使用while(true)从Socket接收数据吗?

问题描述:

请参考我以前的问题代码示例Sockets: sometimes (rarely) packets are lost during receiving我应该使用while(true)从Socket接收数据吗?

我需要始终从UDP多播套接字接收数据。这是单向的通信,我只需要倾听新的数据并尽快处理。

我应该用while(true)?我不喜欢while(true),因为在我看来这会给处理器带来很多额外的工作。可能c#提供其他回调技术或什么?

+1

你使用什么特定的呼叫来侦听新的数据包?有很多方法可以完成,而且很重要。另外:应用程序的性质是什么?它也收听了多少个广播?如果只是这一个(或几个),那么专用线程和阻塞读取调用可能不是问题。对于数十或数百或数千个连接的专用服务器,您一定要使用回调IO或Socket.Select。 – 2012-03-23 06:54:22

+0

@MarcGravell我应该听几个套接字(从2到6),我为每个套接字使用专用线程。我在每个套接字上每秒接收约2000个数据包 – javapowered 2012-03-23 06:58:50

2至6插槽(评论)大概是有趣的地方阻塞或异步IO将正常工作,因为你没有使用线程淹没了机器在那里。每秒有2000个数据包,这听起来像是有足够的线程繁忙。你不需要担心while(true)性能的角度来看,因为Receive方法会阻塞,直到数据可用,所以它是永远不会做一个无所事事的热循环。然而!就个人而言,从美容的角度来看,我同意while(true)是不必要的印迹,因此,如果您使用的是阻塞的方法,也许考虑:

int bytesRead; 
while((bytesRead = socket.Receive(buffer)) > 0) { 
    // process bytesRead from buffer 
} 

当套接字被关闭,这将完全退出。

也可以与任BeginReceiveSocket.ReceiveAsync方法,不使用阻塞调用做到这一点,而是使用一个事件或回调。这些在处理大量连接时特别有用。

个人的,我倾向于做的是使用Socket.Available;如果这是肯定的,那么有数据缓冲并准备好消耗,因此可以使用简单的Receive即时获取该数据并且没有上下文切换。如果它是零,那么没有数据是目前可用,所以异步呼叫可能更合适。这平衡了上下文切换与直接调用。需要注意的是ReceiveAsync方法已经这个建于太,通过返回值从ReceiveAsync(这是true如果操作是不完整的,并且回调将在以后调用 - 和false如果操作已经完整,没有回调将被调用)。

+0

谢谢Marc。我假设我的任务(从多个UDP套接字接收多播数据)非常普遍,应该有“理想”的解决方案。这是人们需要做的事情来观看IP电视或收音机,并从我的情况下接收“证券交易所”的数据。我确定“推荐使用”的代码示例应该是某处可能甚至在MSDN的某处。也许有人可以链接这样的代码示例... – javapowered 2012-03-23 08:59:39

+0

也可能你知道我为什么失去了pacekts :(看到我的链接问题 – javapowered 2012-03-23 09:17:51

+1

@javapowered呃是...因为你使用UDP **,这是正常的 – 2012-03-23 09:18:35

套接字编程的最佳方式是使用它们的异步对应方法。您应该调用BeginReceive并设置它的回调方法,而不是运行无限循环,而传输完成后会触发。这样你将保持对你的应用程序的控制,并使用更少的资源。

参考:http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx#Y0

+1

“最佳”方式几乎总是取决于上下文中的一小部分...... – 2012-03-23 06:59:23

+0

没有什么可以反对的。从现在开始,我的答案会更精确:) – 2012-03-23 07:03:59

异步方法是最好的解决方案。

然而,在这种情况下,如果你使用,而(真),其中包含socket.Receive(BUF)有一个为处理器没有额外的工作,因为如果你没有设置超时sockect阻止循环,直到数据到达。