1

私は .NETMF アプリケーションに UDP サーバーを持っています (UdpClient などのいくつかのクラスとメソッドがないことを除いて、ソリューションはおそらく従来の .NET Framework 4.5 と同様です)。次のようなソケットで「リッスンを開始」します。

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

そして今、複数のスレッド (IPEndPoint ごとに 1 つのスレッド) からデータを受け入れたいと考えています。ポイントはスピードを最大化することです。(私は .NETMF を使用しているため、UdpClient クラスは利用できないことに注意してください)。

私には2つのアイデアがありました。まず、期待されるデータごとにスレッドを作成し、IPEndPointそこでデータを受け入れ/処理します。ただし、問題は、スレッドがデータを受け入れ、受け入れられたソース IP/ポートがこのスレッドに割り当てられた IP/ポートとは異なると判断した後、このデータが破棄され、他の適切なスレッドで使用できなくなることです。それを修正する簡単な方法はありますか?ここでサンプルコードを参照してください:

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();
        }
    }
}

もう 1 つのアイデアは、データを受け入れるスレッドを 1 つ持つことです。データ チャンクが受け入れられると、ソース IP/ポートに基づいて、このスレッドはデータを処理するための新しいスレッドを作成します。この方法は、毎秒数十または数百のスレッドを作成する必要があるため、あまりエレガントではないようです。予想される IPEndPoint ごとにスレッドを作成し、特定の End Point のデータが利用可能になるまでスレッドを一時停止状態に保つことで、多少の改善が得られるでしょう。

この問題の解決策を教えてください。

ご尽力いただきありがとうございます。

更新 自然なアプローチは次のようになります。

_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
}

ただし、送信者のアドレスに基づいてデータを処理する必要があります。したがって、おそらく次のような同様の意味を持つ行を追加できます。

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

データを受信するたびに実行しますが、サーバーは毎秒数十から数百のメッセージを受信するため、これもエレガントではありません。

私の問題に対する最適な解決策を提案してください。

4

1 に答える 1

2

まず、次のような埋め込み処理を行う場合: 作業を処理するためだけにスレッドを生成しないでください。キュー データ構造を使用して、要求に応答できるように (つまり、情報を分割して) 必要なだけの情報を格納します。2 つのシステム スレッドを使用します。1 つは IO を実行し、もう 1 つは応答を処理します。メッセージをキューに入れるかどうかは、最初のものに決定させます。そうしないと、リクエストが来るたびにスレッドを生成するだけで、パケットフラッドやその他の DoS エクスプロイトの影響を受けやすくなります。それはあなたの限られた記憶を食い尽くすでしょう。キューに妥当な数を超えるパッケージがある場合は、パッケージの受け入れを停止します。

キューに処理するパッケージがある場合は、2 番目のスレッドを起動させます。別のキューで送信される応答を準備します (送信メールなど)。キューにアイテムがなくなると、それ自体がスリープ状態になります。

作業が計算集約的である場合は、Run time Loadable プロシージャを使用して作業を高速化します。

于 2013-04-27T15:58:24.243 に答える