2012-03-23 41 views
6

請參考我以前的問題代碼示例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

回答

3

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

1

套接字編程的最佳方式是使用它們的異步對應方法。您應該調用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

0

異步方法是最好的解決方案。

然而,在這種情況下,如果你使用,而(真),其中包含socket.Receive(BUF)有一個爲處理器沒有額外的工作,因爲如果你沒有設置超時sockect阻止循環,直到數據到達。