-1

I am working my way trough socket tutorials and I am running in to a problem. I have 3 classes; Server, ServerClient and Client. The Server listens for connections requests, the ServerClient is the server side Socket wrapper and the Client is a user side program trying to connect.

The problem I am facing, is that when the Server passes the accepted socket to the ServerClient class the Socket is disconnected. If I debug the Socket passed has Connected = True, but when I set the local variable in ServerClient it becomes Connected = False.

On the Client side I am not facing problems yet know to me, that Socket remains Connected.

What am I doing wrong, and what else sucks about my code?

Server:

    public async void Run()
    {
        //
        if (AcceptingClients)
        {
            // Error already running
            return;
        }

        //
        LoadSettings();

        //
        IPEndPoint localEndPoint = new IPEndPoint(_settings.Ip, _settings.Port);

        // Start The Server
        _server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _server.Bind(localEndPoint);
        _server.Listen(100);

        // 
        AcceptingClients = true;

        //
        OnServerStart(EventArgs.Empty);

        // Running => Accept connections
        await AcceptConnections();

        // Stopped => Close connections
        await CloseConnections();

        // Server Stopped => Finish stuff

        //
        OnServerStop(EventArgs.Empty);
    }
    private async Task AcceptConnections()
    {
        await Task.Run(() =>
        {
            while (AcceptingClients)
            {
                try
                {
                    // Set the _acceptConnectionDone to nonsignaled state.  
                    _acceptConnectionDone.Reset();

                    //
                    _server.BeginAccept(AcceptConnectionsCallback, _server);

                    // Wait until a connection is made before continuing.  
                    _acceptConnectionDone.WaitOne();
                }
                catch
                {
                    //
                }
            }
        });
    }
    private static void AcceptConnectionsCallback(IAsyncResult ar)
    {
        // Signal the AcceptConnections Task to continue.  
        _acceptConnectionDone.Set();

        // 
        if (!AcceptingClients)
        {
            // Server Stopping or stopped
            return;
        }

        // Get the socket that handles the client request.  
        Socket server = (Socket)ar.AsyncState;
        Socket client = server.EndAccept(ar);

        // Create the client object.  
        ServerClient newclient = new ServerClient(client);

        // Add Events


        //
        _connections.TryAdd(_totalConnectionCount++, newclient);
    }

ServerClient:

    private readonly Socket _connection;

    //
    public ServerClient(Socket s)
    {
        //
        _connection = s;

        //
        Run();

        // Disconnected or needs to be disconnected => Process
        Disconnect();
        return;
    }
    private async void Run()
    {
        //
        if (_connection.Connected)
        {
            //
            _connection.ReceiveBufferSize = ServerExt.ReadBufferSize;
            _connection.SendBufferSize = ServerExt.SendBufferSize;
            _connection.NoDelay = true;

            //
            await ListenToClient();
        }
    }

Client:

    public async void Connect()
    {
        if (_connection != null)
        {
            // Check if we are not connected already

        }

        //
        LoadSettings();

        //
        try
        {
            //
            IPEndPoint remoteEndPoint = new IPEndPoint(_settings.Ip, _settings.Port);

            // Create a TCP/IP socket.  
            _connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            {
                ReceiveBufferSize = ServerExt.ReadBufferSize,
                SendBufferSize = ServerExt.SendBufferSize,
                NoDelay = true
            };

            // Connect to the remote endpoint.  
            _connection.Connect(remoteEndPoint);

            //
            if (_connection.Connected)
            {
                //
                await ListenToServer();
            }
        }
        catch
        {
            //

        }

        // Disconnected or needs to be disconnected => Process
        Disconnect();
        return;
    }

Thnx.

Eric S.
  • 31
  • 5
  • Without a good [mcve], it won't be possible to help you with all the problems in the code. But as for your disconnecting issue, it's happening **because you are disconnecting the socket**. The last thing you do in the `ServerClient` constructor is call some `Disconnect()` method. No doubt, this method disconnects or otherwise closes the socket. Hence your problem. – Peter Duniho Aug 18 '17 at 04:20
  • No that is not it, because the Disconnect is not called till after await ListenToClient(); and that is not finishing. Besides atm the Disconnect() is empty. – Eric S. Aug 18 '17 at 07:11
  • _"the Disconnect is not called till after await ListenToClient();"_ -- **yes, it is it.** Your `Run()` method returns as soon as `ListenToClient()` returns an incomplete task. It would be a horrible design to have a constructor block for some extended period of time (so even if you were right, your code would be terribly broken), but you are completely wrong about how `await` works. The `Run()` method returns _before_ the `await` completes, allowing the constructor to finish executing, including calling `Disconnect()`. – Peter Duniho Aug 18 '17 at 07:31
  • You are right, I retested the code now that I can keep the socket connected. I never got to this part since ListenToClient() was never triggered due to the socket being disconnected. Anyway I changed my code to posted below. – Eric S. Aug 18 '17 at 09:33

1 Answers1

0

I managed to keep the connection open by changing the code for ServerClient.

    public ServerClient(int id, Socket s, ClientConnectedDelegate connected, ClientDisconnectedDelegate disconnected)
    {
        //
        Id = id;

        //
        _connection = s;
        _disconnected = disconnected;

        //
        Ip = _connection.RemoteIp();

        //
        _connection.ReceiveBufferSize = ServerExt.ReadBufferSize;
        _connection.SendBufferSize = ServerExt.SendBufferSize;
        _connection.NoDelay = true;

        //
        _netStream = new NetworkStream(_connection, FileAccess.ReadWrite);

        //
        if (_cert != null)
        {
            _ssl = new SslStream(_netStream, false);
            _ssl.AuthenticateAsServer(_cert, false, SslProtocols.Tls, true);

            // 
            _br = new BinaryReader(_ssl, Encoding.UTF8, false);
            _bw = new BinaryWriter(_ssl, Encoding.UTF8, false);
        }
        else
        {
            _br = new BinaryReader(_netStream, Encoding.UTF8, false);
            _bw = new BinaryWriter(_netStream, Encoding.UTF8, false);
        }

        //
        Task.Factory.StartNew(ListenToClient);

        //
        connected(this);
    }
Eric S.
  • 31
  • 5