Question

I have a GUI with 2 buttons and a text box. Button1 starts a server and has it listen for clients. Button 2 sends a connection request to the server and starts to listen for anything the server will send to the client (responses). Although w/ my current code when the Server sends the reply and I try to write it to a text box the whole system hangs.

Code as seen below: Server Class:

class Server
{
    private TcpListener tcpListener;
    private Thread listenThread;


    private void ListenForClients()
    {
        this.tcpListener.Start();

        while (true)
        {
            //blocks until a client has connected to the server
            TcpClient client = this.tcpListener.AcceptTcpClient();

            //create a thread to handle communication 
            //with connected client
            Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
            clientThread.Start(client);
        }
    }
    private void HandleClientComm(object client)
    {
        TcpClient tcpClient = (TcpClient)client;
        NetworkStream clientStream = tcpClient.GetStream();

        byte[] message = new byte[4096];
        int bytesRead;

        while (true)
        {
            bytesRead = 0;

            try
            {
                //blocks until a client sends a message
                bytesRead = clientStream.Read(message, 0, 4096);
            }
            catch
            {
                //a socket error has occured
                break;
            }

            if (bytesRead == 0)
            {
                //the client has disconnected from the server
                break;
            }

            //message has successfully been received
            ASCIIEncoding encoder = new ASCIIEncoding();

            byte[] buffer = encoder.GetBytes("Hello Client!");
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
        }
        tcpClient.Close();
    }
    public Server()
    {
        this.tcpListener = new TcpListener(IPAddress.Any, 3000);
        this.listenThread = new Thread(new ThreadStart(ListenForClients));
        this.listenThread.Start();
    }
}

GUI class:

    private void buttonServerStart_Click(object sender, EventArgs e)
    {
        Server Myserver  = new Server();
    }

    //Greet the Server and listen for response...
    private void EthStartB_Click(object sender, EventArgs e)
    {
        TcpClient client = new TcpClient();
        byte[] message = new byte[4096];
        int bytesRead;
        IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);

        client.Connect(serverEndPoint);

        NetworkStream clientStream = client.GetStream();

        ASCIIEncoding encoder = new ASCIIEncoding();
        byte[] buffer = encoder.GetBytes("Hello Server!");

        clientStream.Write(buffer, 0, buffer.Length);
        clientStream.Flush();
        //start listening            
        this.ClientListener.Start();
        while (true)
        {
            bytesRead = 0;

            try
            {
                //blocks until a client sends a message
                bytesRead = clientStream.Read(message, 0, 4096);
            }
            catch
            {
                //a socket error has occured
                break;
            }

            if (bytesRead == 0)
            {
                //the client has disconnected from the server
                break;
            }

            //message has successfully been received
            tb_recieved.Clear();
            tb_recieved.Text=encoder.GetString(message,0,bytesRead);
        }
    }
    TcpListener ClientListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 3000);
    private void EthEndB_Click(object sender, EventArgs e)
    {
        Form3 frmT = new Form3();
        frmT.Show();
    }       

}

The issue is when private void EthStartB_Click(object sender, EventArgs e) calls the code line of tb_recieved.Text=encoder.GetString(message,0,bytesRead);

Was it helpful?

Solution

The program hangs because you have a while(true) loop in EthStartB_Click which runs on UI thread. clientStream.Read call will block UI thread.

Move the receive logic on a new thread and set the textbox content using Control.Invoke or Dipatcher.Invoke depending on whether you are on WinForms or WPF - and do that only if you do have some content in the message to be written to textbox.

There also another issue, since you have the tcpClient.Close() outside the while loop on the server, neither client nor server will disconnect. Both will block on their respective stream.Read calls.

Since you are running both client and server on same machine, that TcpListener ClientListener is not required and will not play well with the server already listening on the same port.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top