我一直試圖讓我的服務器應用程序在客戶端與其斷開連接時在標籤中顯示消息。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」或您可以監控的事件? –