C#TCP客户端在收听服务器和更新GUI时遇到问题

时间:2013-12-06 22:04:31

标签: c# visual-studio-2010 tcp tcplistener

我有一个带有2个按钮和一个文本框的GUI。 Button1启动服务器并让它监听客户端。按钮2向服务器发送连接请求,并开始侦听服务器将发送给客户端的任何内容(响应)。虽然我在服务器发送回复时使用当前代码,但我尝试将其写入文本框,整个系统都会挂起。

代码如下所示: 服务器类:

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类:

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

}

问题是private void EthStartB_Click(object sender, EventArgs e)调用tb_recieved.Text=encoder.GetString(message,0,bytesRead);

的代码行时

1 个答案:

答案 0 :(得分:2)

程序挂起,因为while(true)中的EthStartB_Click循环在UI线程上运行。 clientStream.Read调用将阻止UI线程。

在新线程上移动接收逻辑,并使用textboxControl.Invoke设置Dipatcher.Invoke内容,具体取决于您是使用WinForms还是WPF - 并且仅在您确实拥有时才这样做message中的一些内容要写入文本框。

还有另一个问题,因为服务器上有tcpClient.Close() 外部 while循环,客户端和服务器都不会断开连接。两者都会阻止他们各自的stream.Read来电。

由于您在同一台计算机上同时运行客户端和服务器,因此不需要TcpListener ClientListener,并且对于已在同一端口上侦听的服务器将无法正常运行。