2010-03-03 43 views
3

我目前正在創建一個Windows服務,它將創建到多臺機器(所有機器上的相同套接字)的TCP連接,然後偵聽這些機器上的「事件」。我試圖編寫代碼來創建一個連接,然後產生一個線程,該線程偵聽等待來自機器的數據包的連接,然後解碼出現的數據包,並根據數據包的有效負載調用函數。在C#中創建多個TCP連接,然後等待數據

問題是我不完全知道如何在C#中做到這一點。有沒有人有任何有用的建議或鏈接可能會幫助我做到這一點?

在此先感謝您的幫助!

+0

查看框架中的IHttpAsyncListener。它可能會爲你做很多工作。 – 2010-03-03 03:58:23

回答

2

您可以異步接收每一個套接字連接,並解碼來自其他機器來執行任務中的數據(您可以找到有關異步方法的一些有用的信息這裏:http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx)。

要創建連接,你可以這樣做:

Socket sock = Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
sock.Connect(new IPEndPoint(address, port)); 

相同的方式,可以建立多個連接並保持在字典的列表(無論你喜歡)有引用。

用於異步接收套接字上的數據,你可以這樣做:

sock.BeginReceive(buffer, 0, buffer.len, SocketFlags.None, new AsyncCallback(OnDataReceived), null); 

方法OnDataReceived將被調用時接收操作完成。

OnDataReceived方法你要做的:

void OnDataReceived(IAsyncResult result) 
{ 
    int dataReceived = sock.EndReceive(result); 
    //Make sure that dataReceived is equal to amount of data you wanted to receive. If it is 
    //less then the data you wanted, you can do synchronous receive to read remaining data. 

    //When all of the data is recieved, call BeginReceive again to receive more data 


    //... Do your decoding and call the method ...// 
} 

我希望這可以幫助你。

0

有一個單線程運行accept()來獲取新的連接。對於您獲得的每個新連接,使用線程池生成一個工作線程。

4

根據您計劃支持的併發客戶數量,每個連接線程體系結構可能會很快崩潰。原因在於,每個線程都需要大量資源。默認情況下,每個.NET線程獲得1MB的堆棧空間,因此每個連接1MB加上任何開銷。

相反,當支持多個連接的客戶端時,通常會使用asynchronous methodssee here also),因爲Windows將使用「完成端口」,在等待某個事件完成時基本釋放該線程以執行其他操作。

爲此,你會看的方法,如BeginAccept,BeginReceive,BeginSend等

更簡單的方法也避免了使阻塞調用,避免了多線程是使用Socket.Select方法在一個循環。這允許單個線程服務多個套接字。該線程一次只能物理讀取或寫入一個套接字,但想法是您正在檢查多個套接字的狀態,這些套接字可能包含或不包含要讀取的數據。

在任何情況下,每次連接的方法都會讓您的頭腦變得簡單得多,但它確實存在嚴重的可伸縮性問題。我建議先用接受,接收,發送等同步方法來做這件事。然後再重構你的代碼以使用異步方法,這樣你就不會耗盡服務器的內存。

0

我不知道在你的情況下是否可能,但你有沒有想過使用多臺機器調用的WCF服務?你可以在一個自定義的Windows服務或IIS中承載它。在等待事件時它將消耗非常少的資源,而且編碼要比所有低級可怕套接字的東西簡單得多。它是自動異步的。你得到了很好的消息給你的服務,而不是你需要反序列化和/或解析的數據包。您可以使用任何數量的協議,例如REST或二進制。

您當然需要在發送消息的另一端創建進程。

只是一個想法...

乾杯