我一直试图让我的服务器应用程序在客户端与其断开连接时在标签中显示消息。TCPClient断开连接时显示消息
现在,标签显示客户端启动时连接的客户端的IP地址,但当客户端关闭时,IP地址仍显示在标签中。
我到目前为止已经试过这些方法没有任何的运气:
// DETECT IF CLIENT DISCONNECTED
//METHOD 1
if (bytesRead == 0)
{
ClientIPLabel.Text = "(No Clients Connected)";
break;
}
//METHOD 2
if (!tcpListener.Pending())
{
ClientIPLabel.Text = "(No Clients Connected)";
}
//METHOD 3
if (tcpClient.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (tcpClient.Client.Receive(buff, SocketFlags.Peek) == 0)
{
ClientIPLabel.Text = "(No Clients Connected)";
}
我敢肯定,很可能一些简单的我失踪,我只是无法弄清楚它是什么。
编辑:我发现有些地方,当我点击关闭我的客户端应用程序的按钮,客户端发送消息到服务器关闭之前的一种解决方法。服务器知道,如果它收到此特定消息(在本例中为“SHUTDOWN CLIENT”)以将“ClientIPLabel.text”中的文本更改为“(无客户端已连接)”
这对大多数情况,但它有点破解,并且如果客户端由于错误或崩溃等原因而关闭,服务器就不知道它已经断开连接,所以它仍然会显示它发送的最后一个已知IP。
第二编辑:因此看起来解决方法不适用于我。在将其添加到我的项目中后,出于某种原因,无论客户端向服务器发送什么消息都会显示“(无客户端已连接)”消息。
我的客户仍然是实际连接和接收消息,但“ClientIPLabel”的标签不正确
3日编辑:这是表示我有一个片段我客户端设置发送邮件服务器为每详见下面我的意见之一:
private void SendMessage(string msg)
{
NetworkStream clientStream = ConsoleClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
4日编辑:我的服务器代码,与我直接从客户端关机按钮来获取客户端断开消息暂时的解决办法:
public partial class Server : Form
{
private TcpListener tcpListener;
private Thread listenThread;
private delegate void WriteMessageDelegate(string msg);
public Server()
{
InitializeComponent();
Server();
}
// WAIT FOR CLIENT
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
// GET CLIENT IP ADDRESS
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
string clientIPAddress = "" + IPAddress.Parse(((IPEndPoint)client.Client.RemoteEndPoint).Address.ToString());
ClientIPLabel.Text = clientIPAddress;
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
// COMMUNICATE WITH 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
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
// CHECK FOR CLIENT DISCONNECT
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
5日编辑:我已经更新我的代码,我已经(几乎)得到了心跳计时器的实现,但它仍然没有设置完全正确...这是我的代码:
// CHECK FOR CLIENT DISCONNECT
// SHUTDOWN BUTTON PRESSED
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
// CHECK FOR CONNECTION FAILED
void heartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
HandleClientComm("Check for connection");
}
catch (Exception)
{
Invoke((MethodInvoker)delegate
{
ClientIPLabel.Text = "(No Clients Connected)";
});
}
}
无论我的客户端是否已断开连接,“(无客户端已连接)”消息会在计时器后自动弹出,因此它没有正确捕获异常。
我试过在他写这篇文章的时候实现了interceptwind的建议,但是由于某种原因,我应该有catch (Exception e)
我只有在我摆脱e
并将它写为catch (Exception)
时才能构建它。如果我离开e
那里,我收到一条警告,说"The variable 'e' is declared but never used"
。我知道interceptwind写他的例子使用我的SendMessage()方法,但该方法只用于我的客户端,所以我改变了代码尝试使用我的HandleClientComm()方法,所以我想知道如果这是这个工作不正常的原因。我尝试过改变一些东西,但仍似乎无法得到它的工作。 5秒后,即使我的客户端仍然连接并正常工作,我仍然收到“(无客户端连接)”消息。
6日编辑:我试图调节我的HandleClientComm()
方法能够发送邮件,但我显然错过了一些东西,因为我的“心跳计时器”仍是我的切换到ClientIPLabel.text“ (无客户端连接)“,即使我的客户端仍然连接。
这里是我的代码:
// COMMUNICATE WITH CLIENT
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] message = new byte[4096];
byte[] buffer = encoder.GetBytes("Send Message");
int bytesRead;
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
// START HEARTBEAT TIMER
System.Timers.Timer heartbeatTimer = new System.Timers.Timer();
heartbeatTimer.Interval = 5000;
heartbeatTimer.Elapsed += heartbeatTimer_Elapsed;
heartbeatTimer.Start();
// CHECK FOR CLIENT DISCONNECT
// SHUTDOWN BUTTON PRESSED
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
if (msg.Equals("Client Disconnected (" + DateTime.Now + ")"))
{
ClientIPLabel.Text = ("(No Client Connected)");
}
}
tcpClient.Close();
}
// CHECK FOR CONNECTION FAILED
void heartbeatTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
HandleClientComm("Check for connection");
}
catch (Exception)
{
Invoke((MethodInvoker)delegate
{
ClientIPLabel.Text = "(No Clients Connected)";
});
}
}
您的服务器应用程序有一个GUI? –
是的,它只是坐在系统托盘中,但它也有一个基本的图形用户界面,您可以打开它显示我的客户端发送给服务器的消息(类似日志),但它也显示当前连接的客户端的IP在GUI的底部。 – Patrick
您用于收听客户端的对象是否有事件,如“OnDisconnected”或您可以监控的事件? –