高udpclient cpu使用

时间:2015-02-26 19:05:50

标签: c# task asyncsocket udpclient dataflow

所以我有一堆我想要监听的不同端口,并且迭代可用数据以发送到Dataflow管道。我总共听了14个端口。 寻找有关如何减少以下代码的CPU使用率的任何建议。

所以我只是将端口传递给方法然后将它们添加到列表中

   public static void AddPorts(Dictionary<int,string> ports)
    {
        try
        {


                var NewEndPoints = new List<IPEndPoint>();
                foreach (var port in ports)
                {
                    var endpoint = new IPEndPoint(IPAddress.Any, port.Key);
                    NewEndPoints.Add(endpoint);
                    if (!Endpoints.Contains(endpoint))
                    {                            
                        Endpoints.Add(endpoint);
                        var client = new UdpClient(endpoint);
                        logger.Info("New Client added on port: {0}", endpoint.Port);
                        Clients.Add(client);

                    }
                    else
                    {
                        if (IgnoredPorts.Contains(endpoint.Port))
                        {
                            logger.Info("Existing client enabled on port: {0}", endpoint.Port);
                            IgnoredPorts.Remove(port.Key);
                        }
                    }
                }
                var differences = Endpoints.Except(NewEndPoints);
                differences.ToList().ForEach(d =>
                {                         
                    if (!IgnoredPorts.Contains(d.Port))
                    {
                        IgnoredPorts.Add(d.Port);
                        logger.Info("Client removed on port: {0}", d.Port);
                    }
                });



        }
        catch (Exception ex)
        {
            logger.Error("Error creating udpclients", ex);
        } 
    }

然后我迭代任何可用的数据

 Task.Run(async delegate
        {

            while (Receive)
            {
                try
                {
                    // get any channels that have data availble
                    // Iterate over the the channels and send to Dataflow pipeline
                    var readyChannels =
                (from channel in Clients
                 where channel.Available > 0 && !ListenersDF.IgnoredPorts.Contains(((IPEndPoint)channel.Client.LocalEndPoint).Port)
                 select channel);

                    // Iterate over the the channels and send to Dataflow pipeline
                    foreach (var channel in readyChannels)
                    {
                        // await on the result of the task
                        await ReceiveAndRespond(channel);
                    }

                }
                catch (Exception ex)
                {
                    logger.Error("Error sending packet to bufferBlock", ex);
                }
            }
        });

最后将其发送到数据流管道

async Task ReceiveAndRespond(UdpClient channel)
    {
        UdpReceiveResult? result = null;

        try
        {
            result = await channel.ReceiveAsync();
        }
        catch (Exception exc)
        {
            logger.Error("Error receiving from channel: " + exc.Message, exc);
        }

        if (result != null)
        {
            var device = (from d in Ports
                          where d.Key == ((IPEndPoint)channel.Client.LocalEndPoint).Port
                          select d.Value).FirstOrDefault();
            UdpData data = new UdpData() { Client = channel, Data = result.Value.Buffer, LocalPort = ((IPEndPoint)channel.Client.LocalEndPoint).Port, LocalIP = ((IPEndPoint)channel.Client.LocalEndPoint).Address, RemoteEndpoint = result.Value.RemoteEndPoint, Device = device };
            Flow.bufferBlock.Post(data);

            // for testing logs the hex string to a log file              
            //logger.Warn(string.Format("Data received on port: {0} for device: {1} with data: {2}", data.LocalPort, data.Device, data.Data.ByteArrayToHexString()));              
        }
    }

然后cpu坐在50%,几乎没有流量,我确定有些事情搞砸了我是怎么做到这一点的。非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

我想,你应该改变你的设计。这是一个示例服务器代码。

public class UDPServer
{
    public UDPServer(IEnumerable<int> listenPorts)
    {
        foreach(var port in listenPorts)
        {
            var udpClient = new System.Net.Sockets.UdpClient();
            udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port));
            udpClient.BeginReceive(Receive, udpClient);
        }
    }

    public void Receive(IAsyncResult ar)
    {
        var udpClient = ar.AsyncState as UdpClient;
        IPEndPoint endPoint = null;
        var data = udpClient.EndReceive(ar, ref endPoint);

        //Do some work and send a response back
        var dataToSend = Encoding.UTF8.GetBytes(String.Concat(Encoding.UTF8.GetString(data).Reverse()));
        udpClient.Client.SendTo(dataToSend, endPoint);

        udpClient.BeginReceive(Receive, udpClient);
    }
}

现在,您可以像这样测试:

var server = new UDPServer(new[] { 10000, 10001, 10002 });
await Task.Delay(2000); //Just to keep the code simple, for now.

var udpClient = new UdpClient();
udpClient.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10001));

while (true)
{
    var line = Console.ReadLine();
    if (line == ".") break;

    var data = Encoding.UTF8.GetBytes(line);
    udpClient.Send(data, data.Length);

    IPEndPoint endPoint = null;
    var recvData = udpClient.Receive(ref endPoint);
    Console.WriteLine(Encoding.UTF8.GetString(recvData));
}