C# Client - Server Socket Disconnect Handling

17,331

Two things I can think of. The documentation on Socket recommends calling Shutdown() first, before Close().

Also, you cannot reuse a socket object. So make sure you're using a new Socket object before trying a new connection, either by _socket = new Socket(), or by using a totally new ServerSocket/ClientSocket.

Share:
17,331
ProToCooL
Author by

ProToCooL

Updated on June 04, 2022

Comments

  • ProToCooL
    ProToCooL almost 2 years

    I've got a client - server code going on at the moment while working on my thesis. And I can spawn a connection and send data, but as soon as the client disconnects and tries to reconnect everything goes sideways and I can't seem to figure out why. Too many exceptions are being thrown and I just have no idea where to start catching them all. What am doing wrong or not doing that isn't allowing nether client nor server to handle disconnections properly ?!

    This is my ServerSide Code:

    using System;
    using System.Net;
    using System.Net.Sockets;
    
    namespace Server.Networking
    {
    public class ServerSocket
    {
        private Socket _socket;
        Byte[] _buffer = new byte[61144];
    
        public ServerSocket()
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
    
        public void Bind(int port)
        {
            _socket.Bind(new IPEndPoint(IPAddress.Any, port));
        }
    
        public void Listener(int backlog)
        {
            _socket.Listen(backlog);
        }
    
        public void Accept()
        {
            _socket.BeginAccept(AcceptedCallback, null);
        }
    
        private void AcceptedCallback(IAsyncResult result)
        {
            try
            {
                Socket clientSocket = _socket.EndAccept(result);
                if (clientSocket.Connected)
                {
                    Console.WriteLine("Client has connected!");
                    _buffer = new byte[61144];
                    clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
                    Accept();
                }
                else
                {
                    Console.WriteLine("Client hasn't connected!");
                    return;
                }
            }catch(SocketException ex)
            {
                Console.WriteLine(ex.Message);
                close(clientSocket);
            }
        }
    
        private void ReceivedCallback(IAsyncResult result)
        {
            try
            {
                Socket clientSocket = result.AsyncState as Socket;
                SocketError SE;
                int bufferSize = clientSocket.EndReceive(result, out SE);
                if (bufferSize > 0)
                {
                    if (SE == SocketError.Success)
                    {
                        byte[] packet = new byte[bufferSize];
                        Array.Copy(_buffer, packet, packet.Length);
                        Console.WriteLine("Handling packet from IP:" + clientSocket.RemoteEndPoint.ToString());
                        //Handle packet stuff here.
                        PacketHandler.Handle(packet, clientSocket);
                        _buffer = new byte[61144];
                        clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
                    }
                    else
                    {
                        close(clientSocket);
                    }                    
                }
                else
                {
                    Console.WriteLine("Probably received bad data.");
                    close(clientSocket);
                }
            }
            catch (SocketException ex)
            {
                Console.WriteLine(ex.Message);
                close(clientSocket);
            }
        }
    
        public void close(Socket sock)
        {
            Console.WriteLine("Closing socket for IP:" + sock.RemoteEndPoint.ToString() + " and releasing resources.");
            sock.Dispose();
            sock.Close();
        }
    }
    }
    

    And this is my ClientSide Code:

    using System;
    using System.Net;
    using System.Linq;
    using System.Net.Sockets;
    using Client.Networking.Packets;
    using System.Net.NetworkInformation;
    using Client.Networking.Packets.Request;
    
    namespace Client.Networking
    {
    public class ClientSocket
    {
        private Socket _socket;
        private byte[] _buffer;
    
        public delegate void RaiseConnect(object source, TextArgs e);
        public static event EventHandler Disconnected;
        private static void RaiseDisconnect()
        {
            EventHandler handler = Disconnected;
            if(handler !=null)
            {
                handler(null, EventArgs.Empty);
            }
        }
    
        public ClientSocket()
        {
            udpbroadcast.Connect += new RaiseConnect(OnConnectRaise);
        }
    
        public string machineIP()
        {
            return Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
        }
    
        private void OnConnectRaise(object sender, TextArgs e)
        {
            CheckRegisteredRequest computer_name = new CheckRegisteredRequest(Environment.MachineName.ToString() + "," + machineIP());
            Connect(e.Message, 6556);
            Send(computer_name.Data);
        }
    
        public void Connect(string ipAddress, int port)
        {
            string ip = ipAddress;
            int porT = port;
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IAsyncResult result =_socket.BeginConnect(new IPEndPoint(IPAddress.Parse(ip), port), ConnectCallback, null);
            bool success = result.AsyncWaitHandle.WaitOne(5000, true);
            if(!success)
            {
                _socket.Close();
                Console.WriteLine("Failed to connect to server. Trying again.");
                Connect(ip, port);
            }
        }
    
        private void ConnectCallback(IAsyncResult result)
        {
            try {
                if (_socket.Connected)
                {
                    Console.WriteLine("Connected to the server!");
                    _buffer = new byte[61144];
                    _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, null);
                }
                else
                {
                    Console.WriteLine("Could not connect.");
                    Close(_socket);
                }
            }
            catch(SocketException ex)
            {
                Console.WriteLine("ClientSocket ConnectCallback - "+ex.Message);
                Close(_socket);
            }
        }
    
        private void ReceivedCallback(IAsyncResult result)
        {
            try
            {
                SocketError SE;
                int buflength = _socket.EndReceive(result, out SE);
                if (buflength > 0)
                {
                    if(SE == SocketError.Success)
                    {
                        byte[] packet = new byte[buflength];
                        Array.Copy(_buffer, packet, packet.Length);
    
                        //Handle the Package
                        PacketHandler.Handle(packet, _socket);
    
                        _buffer = new byte[61144];
                        _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, null);
                    }
                    else
                    {
                        Close(_socket);
                    }
                }
                else
                {
                    Close(_socket);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ClientSocket ReceivedCallback - " + ex.Message);
                Close(_socket);
            }
        }
    
        public void Send(byte[] data)
        {
            byte[] send = new byte[data.Length];
            send = data;
            if( _socket.Connected)
            {
                _socket.Send(data);
            }
            else
            {
                Console.WriteLine("Not connected yet!");
                Close(_socket);
            }
        }
    
        public bool connectionStatus()
        {
            return _socket.Connected;
        }
    
        public static void Close(Socket sock)
        {
            Console.WriteLine("Closing the socket and releasing resources.");
            sock.Dispose();
            sock.Close();
            RaiseDisconnect();
        }
    }
    }
    
    • Alexandru
      Alexandru over 8 years
      Check my answer here (BeginAccept needs to be called again everytime clients connects in order to accept new connections; I recommend threading this out): stackoverflow.com/questions/30688760/…