C # Асинхронная сеть UDP, ошибка 10057 - PullRequest
0 голосов
/ 17 февраля 2012

Я пытался заставить этот асинхронный UDP-сервер работать в течение последних двух дней и сейчас бью себя об стену.

В настоящее время я получаю SocketException для 10057, когда пытаюсь получить RemoteEndPoint из Socket в ReceiveCallback.

При просмотре с помощью отладчика socket заполнено, state заполнено. LocalEndPoint обычно устанавливается на {0.0.0.0:53}, но RemoteEndPoint говорит, что SocketException было брошено. И я не понимаю, чего мне не хватает в моей настройке. Любые подсказки, советы, рекомендации приветствуются.

namespace UDPServer
{
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;

    public class StateObject
    {
        // Client socket
        public Socket socket = null;

        // Size of the receive buffer
        public const int BufferSize = 1024;

        // Receive buffer
        public byte[] buffer = new byte[BufferSize];
    }

    public class ServerAsync
    {
        private static int portNumber = 53;
        public static ManualResetEvent WaitEvent = new ManualResetEvent(false);

        public static void StartListening()
        {
            // Data buffer
            byte[] bytes = new byte[1024];

            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, portNumber);
            EndPoint client = new IPEndPoint(IPAddress.Any, 0);
            socket.Bind(localEndPoint);

            Console.WriteLine("Listening for UDP queries on port 53");

            while (true)
            {
                // Set event to non-signaled state.
                WaitEvent.Reset();
                Console.WriteLine("Waiting for a connection...");
                StateObject state = new StateObject();

                state.socket = socket;
                socket.BeginReceiveFrom(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, ref client, new AsyncCallback(ReceiveCallback), state);

                // Wait until a connection is made before continuing.
                WaitEvent.WaitOne();
            }
        }

        public static void ReceiveCallback(IAsyncResult ar)
        {
            // Signal main thread to continue.
            WaitEvent.Set();

            int bytesRead = 0;

            try
            {
                if (ar.IsCompleted)
                {
                    StateObject state = (StateObject)ar.AsyncState;
                    Socket socket = state.socket;

                    IPEndPoint sender = (IPEndPoint)socket.RemoteEndPoint;
                    EndPoint remoteEndPoint = (EndPoint)sender;

                    bytesRead = socket.EndReceiveFrom(ar, ref remoteEndPoint);

                    if (bytesRead > 0)
                    {
                        Console.WriteLine("Received {0} bytes from {1}:{2}: {3}", bytesRead, sender.Address.ToString(), sender.Port.ToString(), BitConverter.ToString(state.buffer));

                        socket.BeginReceiveFrom(state.buffer, 0, StateObject.BufferSize, 0, ref remoteEndPoint, new AsyncCallback(ReceiveCallback), state);
                    }

                }
            }
            catch (SocketException se)
            {
                Console.WriteLine("SocketException: " + se.ErrorCode + ": " + se.Message);
            }
            catch (ObjectDisposedException ode)
            {
                Console.WriteLine("Socket closed: " + ode.Message);
            }
        }

        public static void Main(string[] args)
        {
            Console.WriteLine("Server starting up...");

            StartListening();
        }
    }
}

1 Ответ

1 голос
/ 17 февраля 2012

Почему ваш основной поток зацикливается и читает данные из порта, когда EndCallback также начинает новое чтение?Мне кажется, что два потока будут пытаться читать с порта одновременно, используя один и тот же StateObject.

Кроме того, ваш обратный вызов приема использует буфер AsyncResult для запуска новой операции чтения.Знаете ли вы, что сокет делает с объектом AsyncResult после возврата?Можете ли вы быть уверены, что он не располагает?Возможно, вам потребуется создать новый AsyncResult для каждого запроса на чтение, чтобы они оставались действительно независимыми.

...