ellekaie
ellekaie

Reputation: 337

C# async SocketException while binding

I am working on a client-server application on C# using async sockets. As I listen for connections, I keep getting this error

An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll

Additional information: Only one usage of each socket address (protocol/network address/port) is normally permitted

This is the line where this exception happens:

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

The code is under Listener.Start(int port). In the main program, here's how I call the method:

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

I am testing both the client and server applications in my PC.

Here's the Listener class.

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
                {

                }
            }
        }
    }
    
}

Here's the Client class.

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

Why do I get the SocketException error? Any help is appreciated. Thanks!

Upvotes: 0

Views: 2852

Answers (1)

KirkSpaziani
KirkSpaziani

Reputation: 1972

So the obvious things to check - Something is already listening on port 8192 or there's some other reason why your machine would reject your program opening that port (firewalls, etc).

The other problem is while you are blocking binding twice with the "Running" check, you're only doing that for the instance of listener - hitting the button will create a whole new listener and attempt to have it listen on port 8192 - which since you already have a listener bound there, will fail with that exception.

Upvotes: 1

Related Questions