2014-05-05 100 views
0

我有一個類的記錄在客戶端:TCP套接字快速分組發送

public class LoggedIn_Class 
{ 
    public Socket socket; 
    public string name; 
} 

而且我有一個列表:

public static List<Object> LoggedIn_List = new List<Object>(); 

當有人登錄到我的服務器我將它添加到清單:

LoggedIn_Class newClient = new LoggedIn_Class(); 

newClient.socket = currentSocket; 
newClient.name = currentName; 

LoggedIn_List.Add(newClient); 

現在,我試圖將數據包發送到每一位客戶這樣的:

foreach (LoggedIn_Class s in variables.LoggedIn_List.ToArray()) 
{ 
    s.socket.Send(Packet); 
} 

現在問題是foreach處理過快的項目,它不能發送。這工作正常,但我不認爲這是最好的解決方案...

foreach (LoggedIn_Class s in variables.LoggedIn_List.ToArray()) 
{ 
    s.socket.Send(Packet); 
    Thread.Sleep(50); 
} 

有人對此有任何想法嗎?我能做些什麼來等待發送結束?

+1

您正在使用什麼樣的插座呢?什麼協議?是否有例外?它如何「不起作用」? – Dariusz

+0

'Socket.Send'是一個同步操作 - 只有在你的數據被髮送後纔會返回。你似乎把它與異步混淆(通過你描述它並看着你的方法)。這裏還有其他問題。你有什麼異常或有什麼問題? – oleksii

+0

我正在使用TCP套接字。客戶端只收不到數據包,沒有任何異常。 – David

回答

2

我正在使用TCP套接字。客戶端只收不到數據包,沒有任何異常。

這裏有很多答案。你真正的問題是你還沒有理解基於流的協議的含義。用TCP你不發送消息,你發送字節流。

因此,接收方不能假設在一個socket.Receive中收到的所有內容都對應於與使用socket.Send發送的另一方完全相同的字節。

因此,您應該使用某種機制來檢測何時收到完整的消息。通常情況下,您要麼使用長度前綴爲每個消息加上前綴,要麼在每封消息後使用分隔符。

當您使用Thread.Sleep時,它的工作原因是消息足夠短,一次發送一條消息,並且在發送下一條消息之前設法接收消息。如果沒有延遲,nagle algorithm可能會發揮作用併合並您的消息。

一個天真的實現:

public void Send(byte[] msg) 
{ 
    var header = BitConverter.GetBytes(msg.Length); 
    socket.Send(header, 0, header.Length); 
    socket.Send(msg, 0, msg.Length); 
} 

接收方(可能有問題,但應該給你一個提示):

var buffer = new byte[4]; 
int bytesReceived = socket.Receive(buffer, 0, 4, ....); 
if (bytesReceived < 4) 
{ 
    bytesReceived = socket.Receive(buffer, bytesReceived, 4 - bytesReceived, ....); 
    //this can fail too, probably should use a loop like below until 
    //all four length bytes have been received. 
} 

var bytesToRead = BitConverter.GetInt32(buffer, 0); 
var buffer = new byte[bytesToRead]; 
var offset = 0; 

while (bytesToRead > 0) 
{ 
    var len = Math.Min(bytesToRead, buffer.Length); 
    var read = socket.Receive(buffer, offset, len, .....); 
    bytesToRead -= read; 
    offset += read; 
} 

//now you got everything. 
+0

謝謝你這個好的答案,但你現在推薦什麼?我應該切換到UDP?我正在將類轉換爲字節數組,我試圖將其發送給每個客戶端。我的類通常包含字符串,整數和布爾值。 – David

+0

使用WCF或在字節數組前加一個int。 UDP不可靠,也不按順序發送消息。因此,如果您必須以正確的順序接收每個發送的消息,則UDP更復雜。 – jgauffin

+0

作爲字節數組的前綴是什麼意思?我的數據包的第一個字節總是標題,在客戶端我有一個標題的切換。或者你不是這個意思?對不起,我的英語不好,但我真的不明白。 – David