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

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

图形界面类:

    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); 的代码行时;

最佳答案

程序挂起是因为 EthStartB_Click 中有一个 while(true) 循环,它在 UI 线程上运行。 clientStream.Read 调用将阻塞 UI 线程。

在新线程上移动接收逻辑并使用 Control.InvokeDipatcher.Invoke 设置 textbox 内容在 WinForms 或 WPF 上 - 并且只有在 message 中有一些内容要写入文本框时才这样做。

还有另外一个问题,因为你有 tcpClient.Close() outside 服务器上的 while 循环,无论是客户端还是服务器将断开连接。两者都将阻塞各自的 stream.Read 调用。

由于您在同一台机器上同时运行客户端和服务器,因此不需要 TcpListener ClientListener,并且不会与已经在同一端口上监听的服务器一起正常运行。

关于C# TCP 客户端在监听服务器和更新 GUI 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20434398/

相关文章:

TCP 握手可靠性

c++ - ASIO - 检测死连接

java - TCP 上的对象或字符串 (xml)

c# - 尝试使用 .net 4.0 在 XP sp3 上运行 TLS1.2

c++ - VS2010编译耗时太长

c# Visual Studio 似乎遵循了错误的代码路径

javascript - 如何防止客户端/服务器两侧文本框的sql注入(inject)

c# - ASP.NET Resourcemanager读取本地.resx

c# - 串行通信 - 字节流

c# - 如何将 C# 匿名类型序列化为 JSON 字符串?