TCP Socket快速数据包发送

时间:2014-05-05 12:47:58

标签: c# sockets 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 个答案:

答案 0 :(得分: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.