С# async SocketException при привязке

Я работаю над клиент-серверным приложением на С# с использованием асинхронных сокетов. Когда я слушаю соединения, я продолжаю получать эту ошибку

В System.dll произошло необработанное исключение типа «System.Net.Sockets.SocketException».

Дополнительная информация: обычно разрешено только одно использование каждого адреса сокета (протокол/сетевой адрес/порт).

Это строка, в которой происходит это исключение:

 _listener.Bind(new IPEndPoint(0, port));

Код находится под Listener.Start(int port). В основной программе я вызываю метод следующим образом:

void btnListen_Click(object sender, EventArgs e)
        {
            _listener = new Listener();
            _listener.Accepted += new Listener.SocketAcceptedHandler(listener_Accepted);
            _listener.Start(8192);
        }

Я тестирую клиентские и серверные приложения на своем ПК.

Вот класс Listener.

namespace serverPC
{
    class Listener
    {
        public delegate void SocketAcceptedHandler(Socket e);
        public event SocketAcceptedHandler Accepted;

        Socket _listener;
        public int Port;

        public bool Running
        {
            get;
            private set;
        }

        public Listener() {Port = 0;}

        public void Start(int port)
        {
            if (Running)
                return;

            _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _listener.Bind(new IPEndPoint(0, port)); // This is where the SocketException error occurs
            _listener.Listen(0);

            _listener.BeginAccept(acceptedCallback, null);
            Running = true;
        }

        public void Stop()
        {
            if (!Running)
                return;

            _listener.Close();
            Running = false;
        }

        void acceptedCallback(IAsyncResult ar)
        {
            try
            {
                Socket s = _listener.EndAccept(ar);

                if (Accepted != null)
                {
                    Accepted(s);
                }
            }
            catch
            {

            }

            if (Running)
            {
                try
                {
                    _listener.BeginAccept(acceptedCallback, null);
                }
                catch
                {

                }
            }
        }
    }
    
}

Вот класс Client.

namespace serverPC
{
    struct ReceiveBuffer
    {
        public const int BUFFER_SIZE = 1024;
        public byte[] Buffer;
        public int ToReceive;
        public MemoryStream BufStream;
  
        public ReceiveBuffer(int toRec)
        {
            Buffer = new byte[BUFFER_SIZE];
            ToReceive = toRec;
            BufStream = new MemoryStream(toRec);
        }

        public void Dispose()
        {
            Buffer = null;
            ToReceive = 0;
            Close();
            if (BufStream != null)
                BufStream.Dispose();
        }

        public void Close()
        {
            if (BufStream != null && BufStream.CanWrite)
            {
                BufStream.Close();
            }
        }
    }

    class Client
    {
        byte[] lenBuffer;
        ReceiveBuffer buffer;
        Socket _socket;

        public IPEndPoint EndPoint
        {
            get
            {
                if (_socket != null && _socket.Connected)
                {
                    return (IPEndPoint)_socket.RemoteEndPoint;
                }

                return new IPEndPoint(IPAddress.None, 0);
            }
        }

        public delegate void DisconnectedEventHandler(Client sender);
        public event DisconnectedEventHandler Disconnected;
        public delegate void DataReceivedEventHandler(Client sender, ReceiveBuffer e);
        public event DataReceivedEventHandler DataReceived;

        public Client(Socket s)
        {
            _socket = s;
            lenBuffer = new byte[4];
        }

        public void Close()
        {
            if (_socket != null)
            {
                _socket.Disconnect(false);
                _socket.Close();
            }

            buffer.Dispose();
            _socket = null;
            lenBuffer = null;
            Disconnected = null;
            DataReceived = null;
        }

        public void ReceiveAsync()
        {
            _socket.BeginReceive(lenBuffer, 0, lenBuffer.Length, SocketFlags.None, receiveCallback, null);
        }

        void receiveCallback(IAsyncResult ar)
        { 
            try
            {
                int rec = _socket.EndReceive(ar);

                if (rec == 0)
                {
                    if (Disconnected != null)
                    {
                        Disconnected(this);
                        return;
                    }

                    if (rec != 4)
                    {
                        throw new Exception();
                    }
                }
            }

            catch (SocketException se)
            {
                switch (se.SocketErrorCode)
                {
                    case SocketError.ConnectionAborted:
                    case SocketError.ConnectionReset:
                        if (Disconnected != null)
                        {
                            Disconnected(this);
                            return;
                        }
                        break;
                }
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (NullReferenceException)
            {
                return;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return;
            }

            buffer = new ReceiveBuffer(BitConverter.ToInt32(lenBuffer, 0));

            _socket.BeginReceive(buffer.Buffer, 0, buffer.Buffer.Length, SocketFlags.None, receivePacketCallback, null);

        }

        void receivePacketCallback(IAsyncResult ar)
        {
            int rec = _socket.EndReceive(ar);

            if (rec <= 0)
            {
                return;
            }

            buffer.BufStream.Write(buffer.Buffer, 0, rec);

            buffer.ToReceive -= rec;

            if(buffer.ToReceive > 0)
            {
                Array.Clear(buffer.Buffer, 0, buffer.Buffer.Length);

                _socket.BeginReceive(buffer.Buffer, 0, buffer.Buffer.Length, SocketFlags.None, receivePacketCallback, null);
                return;
            }

            if (DataReceived != null)
            {
                buffer.BufStream.Position = 0;
                DataReceived(this, buffer);
            }

            buffer.Dispose();

            ReceiveAsync();
        }
    }
}

Почему я получаю ошибку SocketException? Любая помощь приветствуется. Спасибо!


person ellekaie    schedule 25.01.2015    source источник


Ответы (1)


Итак, очевидные вещи для проверки: что-то уже прослушивает порт 8192 или есть какая-то другая причина, по которой ваша машина отклоняет вашу программу, открывающую этот порт (брандмауэры и т. д.).

Другая проблема заключается в том, что когда вы дважды блокируете привязку с проверкой «Выполняется», вы делаете это только для экземпляра прослушивателя — нажатие кнопки создаст совершенно новый прослушиватель и попытается заставить его прослушивать порт 8192 — что с тех пор у вас уже есть привязанный слушатель, с этим исключением произойдет сбой.

person KirkSpaziani    schedule 25.01.2015
comment
Нет проблем с первыми вещами, которые вы упомянули. Мой брандмауэр разрешает мое приложение, и ничто другое не слушает порт (я проверял). Я не совсем понимаю, что вы здесь имеете в виду - вы дважды блокируете привязку с помощью проверки выполнения, вы делаете это только для экземпляра слушателя - person ellekaie; 25.01.2015
comment
Теперь я понимаю, что вы имеете в виду в последней части. - person ellekaie; 25.01.2015