我有一个带有 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.Invoke
或 Dipatcher.Invoke
设置 textbox
内容在 WinForms 或 WPF 上 - 并且只有在 message
中有一些内容要写入文本框时才这样做。
还有另外一个问题,因为你有 tcpClient.Close()
outside 服务器上的 while
循环,无论是客户端还是服务器将断开连接。两者都将阻塞各自的 stream.Read
调用。
由于您在同一台机器上同时运行客户端和服务器,因此不需要 TcpListener ClientListener
,并且不会与已经在同一端口上监听的服务器一起正常运行。
关于C# TCP 客户端在监听服务器和更新 GUI 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20434398/