简体   繁体   English

C#UDP多个客户端

[英]C# UDP multiple clients

I have a UDP server in a .NETMF application (the solution would probably be similar for classic .NET Framework 4.5, except that there aren't some classes and methods such as UdpClient). 我在.NETMF应用程序中有一个UDP服务器(该解决方案可能与经典.NET Framework 4.5类似,除了没有诸如UdpClient之类的某些类和方法之外)。 I "start listening" on a socket like this: 我在这样的套接字上“开始监听”:

_server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_server.Bind(ep);

And now I want to accept data from a several threads (one thread for every IPEndPoint). 现在,我想从多个线程(每个IPEndPoint一个线程)接受数据。 The point is to maximize speed. 关键是要最大化速度。 (Note that I am using .NETMF so UdpClient class is not availible). (请注意,我使用的是.NETMF,因此UdpClient类不可用)。

I had two ideas. 我有两个想法。 First was to create a thread for each expected IPEndPoint and accept/process data there. 首先是为每个预期的IPEndPoint创建一个线程并在那里接受/处理数据。 However the problem is that after a thread accepts data and determines that the accepted source IP/port is different than the assigned IP/port to this thread, this data is thrown away and is not availible for the other appropriate thread anymore. 但是问题是,在一个线程接受数据并确定接受的源IP /端口与为此线程分配的IP /端口不同之后,该数据将被丢弃,并且不再可用于其他合适的线程。 Is there a simple way to fix that? 有没有简单的方法可以解决此问题? See sample code here: 在这里查看示例代码:

using System;
using Microsoft.SPOT;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace MFConsoleApplication1
{
    internal class ServerThread
    {
        internal IPEndPoint EP { get; private set; }
        internal Socket Server { get; private set; }
        public ServerThread(IPEndPoint ep, Socket s)
        {
            EP = ep;
            Server = s;
            new Thread(() =>
            {
                byte[] buffer = new byte[2048];
                int byteCount;
                EndPoint recvEP = new IPEndPoint(IPAddress.Any, 0);
                while (true)
                {
                    byteCount = Server.ReceiveFrom(buffer, ref recvEP);
                    if (!recvEP.Equals(EP)) cotinue; //this makes the thread to ignore
                    // to ignore the data as EP is different,but it throw the data away

                    // Process data
                    Debug.Print(byteCount.ToString()); // For example
                }
            }).Start();
        }
    }
}

The other idea is to have one thread which accepts data. 另一个想法是让一个线程接受数据。 When a data chunk is accepted, based on the source IP/port, this thread will create a new Thread to process data. 当数据块被接受时,基于源IP /端口,该线程将创建一个新的线程来处理数据。 This way doesn't seem to be too elegant as it would require creating tens or hundreds of threads per second. 这种方式似乎不太好用,因为它需要每秒创建数十或数百个线程。 A little imporvement would perhaps be to create threads for each expected IPEndPoint, and to keep them in suspended state till a data for the particular End Point is available. 一个小的改进可能是为每个预期的IPEndPoint创建线程,并将它们保持在挂起状态,直到可以使用特定端点的数据为止。

What is the solution of this problem please? 请问该问题的解决办法是什么?

Thanks for any efforts. 多谢您的努力。

Update The natural approach would be: 更新自然的方法是:

_server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_server.Bind(ep);
while (true)
{
    byteCount = Server.ReceiveFrom(buffer, ref recvEP);
    // Process data
    Debug.Print(byteCount.ToString()); // For example
}

However I need to process data on the basis of the address of the sender. 但是,我需要根据发送者的地址来处理数据。 So I could perhaps add a line with similar meaning like: 因此,我也许可以添加一条类似含义的行:

new Thread(new ParameterizedThreadStart(ProcessData)).Start(recvEP);

and execute it each time after some data is received, but as the server receives tens - hundreds of messages per second this woudn't be too elegant either. 并在每次接收到一些数据之后每次都执行它,但是随着服务器每秒接收数十到数百条消息,这也不会太优雅。

Please suggest an optimum solution for my problem. 请为我的问题提出最佳解决方案。

First off, when doing embedded stuff like this: Do not spawn threads just to handle work. 首先,在进行如下嵌入式工作时:不要产生线程只是为了处理工作。 Use a queue data structure and store just enough information so that you can respond to the request (ie parcel the information). 使用队列数据结构并仅存储足够的信息,以便您可以响应请求(即打包信息)。 Use 2 system threads, one that does IO and one that processes responses. 使用2个系统线程,一个执行IO,另一个处理响应。 Let the first one determine if to put a message on the queue. 让第一个决定是否将消息放入队列。 If you don't and you just spawn a thread each time a request comes in you will be susceptible to packet flooding and other DoS exploits; 如果您不这样做,并且每次请求进入时都只是生成一个线程,那么您很容易受到数据包泛洪和其他DoS攻击的影响; that will eat your limited memory. 那会吃掉你有限的记忆。 If there are more than a reasonable number of packages in the queue then stop accepting packages. 如果队列中的软件包数量超过合理数量,则停止接受软件包。

Let the second thread be awoken when there are packages to process on the queue. 当队列中有要处理的程序包时,让第二个线程唤醒。 Let it prepare responses to be sent on another queue (like outgoing mail). 让它准备将响应发送到另一个队列(例如传出邮件)。 When there are no more items on the queue it puts itself to sleep. 当队列中没有更多的项目时,它将进入睡眠状态。

If the work is compute intensive then use a Run time Loadable procedure to accelerate the work. 如果工作是计算密集型的,则使用“运行时可加载”过程来加速工作。

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

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