简体   繁体   English

TCP Socket快速数据包发送

[英]TCP Socket fast packet sending

I have a class of the logged in the clients: 我有一个登录客户端的类:

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

And I have a list: 我有一个清单:

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

When someone login to my server I add it to the list: 当有人登录我的服务器时,我将其添加到列表中:

LoggedIn_Class newClient = new LoggedIn_Class();

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

LoggedIn_List.Add(newClient);

Now I'm trying to send a packet to every client with this: 现在,我正在尝试使用以下方法向每个客户端发送数据包:

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

Now the problem is the foreach processing too fast the items and it can't be send. 现在问题是foreach处理的项目太快而无法发送。 This works properly, but I don't think this is the best solution... 这工作正常,但我不认为这是最好的解决方案......

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

Someone have any idea about this? 有人对此有任何想法吗? What can I do to wait the end of the send? 我该怎么做才能等待发送结束?

I'm using TCP sockets. 我正在使用TCP套接字。 The client just not receive the packets, it don't have any exception. 客户端只是没有收到数据包,它没有任何异常。

There are plenty of answers about this. 关于这个问题有很多答案。 You real problem is that you have not understood what stream based protocols means. 你真正的问题是你还没有理解基于流的协议意味着什么。 With TCP you do not send messages, you send streams of bytes. 使用TCP,您不发送消息,您发送字节流。

As a result, the receiver side can not assume that everything received in one socket.Receive corresponds to exactly the same bytes as the other side sent using socket.Send . 结果,接收方不能假设在一个socket.Receive接收到的所有内容。接收对应于与使用socket.Send发送的另一方完全相同的字节。发送。

You should therefore use some sort of mechanism to detect when a complete message have been received. 因此,您应该使用某种机制来检测何时收到完整的消息。 Typically you either prefix each of your messages with a length prefix or use a delimiter after each message. 通常,您可以使用长度前缀为每条消息添加前缀,也可以在每条消息后使用分隔符。

The reason to why it works when you use a Thread.Sleep is that the messages are short enough to be sent one at a time and you manage to receive them before the next message is sent. 使用Thread.Sleep时它工作原因的原因是消息足够短,一次只能发送一个消息,并且您可以在发送下一条消息之前设置接收消息。 Without the delay, the nagle algorithm probably comes into play and merge your messages. 没有延迟, nagle算法可能会发挥作用并合并你的消息。

A naive implementation: 一个天真的实现:

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

Receiver side (probably faulty, but should give you a hint): 接收方(可能有问题,但应该给你一个提示):

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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM