4

これは私の現在の設定です(UDPを使用):

void OnDataReceived(IAsyncResult result)
{

    IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);

    byte[] buffer = socket.EndReceive(result, ref ep);

    Packet p = new Packet(Encoding.ASCII.GetString(buffer, 0, buffer.Length));

    //process packet

    socket.BeginReceive(new AsyncCallback(OnDataReceived), socket);

}

EndReceiveを呼び出した後すぐにsocket.BeginReceiveを呼び出し、次にパケットを処理して次のような連続的なパケットフローを取得すると、どうなるか疑問に思いました。

void OnDataReceived(IAsyncResult result)
{

    IPEndPoint ep = new IPEndPoint(IPAddress.Any, 0);

    byte[] buffer = socket.EndReceive(result, ref ep);
    socket.BeginReceive(new AsyncCallback(OnDataReceived), socket);

    Packet p = new Packet(Encoding.ASCII.GetString(buffer, 0, buffer.Length));

    //process packets

}

BeginReceiveを呼び出すとすぐにパケットが受信された場合、これは現在のパケット処理と何らかの形で競合しますか?

また、これが競合しない場合、TCPに変更するとこれが機能しなくなりますか?

4

1 に答える 1

5

そこで、ある種の再帰ハンドラーを作成しているようです。それがどのように機能するかはわかりませんが、おそらく良い方法ではありません。私は通常、着信データをリッスンしてイベントに渡す別のリーダースレッドを使用します。これは過去に私に役立ってきました。しかし、私はこれに非同期を使用することを検討していません。

別のスレッドを使用して着信UDPデータを処理する方法のサンプルコードを次に示します。それは完全ではありませんが、それを設定する方法のアイデアをあなたに与えるはずです。

    private Thread _udpReadThread;
    private volatile bool _terminateThread;

    public event DataEventHandler OnDataReceived;
    public delegate void DataEventHandler(object sender, DataEventArgs e);

    private void CreateUdpReadThread()
    {
        _udpReadThread = new Thread(UdpReadThread) { Name = "UDP Read thread" };
        _udpReadThread.Start(new IPEndPoint(IPAddress.Any, 1234));
    }

    private void UdpReadThread(object endPoint)
    {
        var myEndPoint = (EndPoint)endPoint;
        var udpListener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        udpListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

        // Important to specify a timeout value, otherwise the socket ReceiveFrom() 
        // will block indefinitely if no packets are received and the thread will never terminate
        udpListener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 100);
        udpListener.Bind(myEndPoint);

        try
        {
            while (!_terminateThread)
            {
                try
                {
                    var buffer = new byte[1024];
                    var size = udpListener.ReceiveFrom(buffer, ref myEndPoint);
                    Array.Resize(ref buffer, size);

                    // Let any consumer(s) handle the data via an event
                    FireOnDataReceived(((IPEndPoint)(myEndPoint)).Address, buffer);
                }
                catch (SocketException socketException)
                {
                    // Handle socket errors
                }
            }
        }
        finally
        {
            // Close Socket
            udpListener.Shutdown(SocketShutdown.Both);
            udpListener.Close();
        }
    }

    public class DataEventArgs : EventArgs
    {
        public byte[] Data { get; private set; }
        public IPAddress IpAddress { get; private set; }

        public DataEventArgs(IPAddress ipaddress, byte[] data)
        {
            IpAddress = ipaddress;
            Data = data;
        }
    }
于 2012-12-01T20:04:22.637 に答える