2014-05-05 101 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