我正在玩TcpClient,我試圖弄清楚如何使連接屬性在斷開連接時發生錯誤。如何檢查TcpClient連接是否關閉?
我試着做
NetworkStream ns = client.GetStream();
ns.Write(new byte[1], 0, 0);
但它仍然不會告訴我,如果TcpClient的斷開。你會如何使用TcpClient來解決這個問題?
我正在玩TcpClient,我試圖弄清楚如何使連接屬性在斷開連接時發生錯誤。如何檢查TcpClient連接是否關閉?
我試着做
NetworkStream ns = client.GetStream();
ns.Write(new byte[1], 0, 0);
但它仍然不會告訴我,如果TcpClient的斷開。你會如何使用TcpClient來解決這個問題?
據我所知/記住,沒有辦法測試套接字是否連接,而不是讀取或寫入它。
我還沒有使用過TcpClient,但是如果遠程端已經正常關閉,Socket類將從調用返回0來讀取。 如果遠端沒有正常關機[我認爲]你會得到一個超時異常,不記得類型抱歉。
使用像'if(socket.Connected) { socket.Write(...) }
'這樣的代碼創建競爭條件。你最好只是調用socket.Write並處理異常和/或斷開連接。
試試這個,它爲我工作
private void timer1_Tick(object sender, EventArgs e)
{
if (client.Client.Poll(0, SelectMode.SelectRead))
{
if (!client.Connected) sConnected = false;
else
{
byte[] b = new byte[1];
try
{
if (client.Client.Receive(b, SocketFlags.Peek) == 0)
{
// Client disconnected
sConnected = false;
}
}
catch { sConnected = false; }
}
}
if (!sConnected)
{
//--Basically what you want to do afterwards
timer1.Stop();
client.Close();
ReConnect();
}
}
我使用定時器,因爲我想在固定時間間隔 檢查連接狀態,並且不能聽代碼的循環[我覺得這是減緩sending-接收過程]
我不會推薦你嘗試寫測試套接字。並且不要在.NET的Connected屬性上傳遞。
如果你想知道,如果遠程端點仍處於活動狀態,您可以使用TcpConnectionInformation:
TcpClient client = new TcpClient(host, port);
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections().Where(x => x.LocalEndPoint.Equals(client.Client.LocalEndPoint) && x.RemoteEndPoint.Equals(client.Client.RemoteEndPoint)).ToArray();
if (tcpConnections != null && tcpConnections.Length > 0)
{
TcpState stateOfConnection = tcpConnections.First().State;
if (stateOfConnection == TcpState.Established)
{
// Connection is OK
}
else
{
// No active tcp Connection to hostName:port
}
}
client.Close();
另請參見:
TcpConnectionInformation MSDN上
IPGlobalProperties MSDN上
說明TcpState狀態
Netstat Wikipedia
這裏它是作爲TcpClient的擴展方法。
public static TcpState GetState(this TcpClient tcpClient)
{
var foo = IPGlobalProperties.GetIPGlobalProperties()
.GetActiveTcpConnections()
.SingleOrDefault(x => x.LocalEndPoint.Equals(tcpClient.Client.LocalEndPoint));
return foo != null ? foo.State : TcpState.Unknown;
}
這是一個很棒的答案。您可以改進它的唯一方法是將測試作爲返回套接字狀態的Socket擴展方法呈現。 – 2014-08-12 09:45:39
不錯的一個。我真的很想知道是否有更快的方法來做到這一點 – 2015-08-04 04:17:00
謝謝!你的答案是第一個爲我工作的答案。我嘗試過使用client.Client.Poll的各種答案,但他們沒有工作。 – 2016-11-21 15:27:21
@ uriel的答案對我很好,但我需要用C++/CLI編寫代碼,這並不是完全無關緊要的。這裏是(大致相當的)C++/CLI代碼,並添加了一些健壯性檢查以實現良好的度量。
using namespace System::Net::Sockets;
using namespace System::Net::NetworkInformation;
TcpState GetTcpConnectionState(TcpClient^tcpClient)
{
TcpState tcpState = TcpState::Unknown;
if (tcpClient != nullptr)
{
// Get all active TCP connections
IPGlobalProperties^ipProperties = IPGlobalProperties::GetIPGlobalProperties();
array<TcpConnectionInformation^>^tcpConnections = ipProperties->GetActiveTcpConnections();
if ((tcpConnections != nullptr) && (tcpConnections->Length > 0))
{
// Get the end points of the TCP connection in question
EndPoint^localEndPoint = tcpClient->Client->LocalEndPoint;
EndPoint^remoteEndPoint = tcpClient->Client->RemoteEndPoint;
// Run through all active TCP connections to locate TCP connection in question
for (int i = 0; i < tcpConnections->Length; i++)
{
if ((tcpConnections[i]->LocalEndPoint->Equals(localEndPoint)) && (tcpConnections[i]->RemoteEndPoint->Equals(remoteEndPoint)))
{
// Found active TCP connection in question
tcpState = tcpConnections[i]->State;
break;
}
}
}
}
return tcpState;
}
bool TcpConnected(TcpClient^tcpClient)
{
bool bTcpConnected = false;
if (tcpClient != nullptr)
{
if (GetTcpConnectionState(tcpClient) == TcpState::Established)
{
bTcpConnected = true;
}
}
return bTcpConnected;
}
希望這會幫助某人。
我已經創建了這個函數,併爲我檢查客戶端是否仍然與服務器連接。
/// <summary>
/// THIS FUNCTION WILL CHECK IF CLIENT IS STILL CONNECTED WITH SERVER.
/// </summary>
/// <returns>FALSE IF NOT CONNECTED ELSE TRUE</returns>
public bool isClientConnected()
{
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections();
foreach (TcpConnectionInformation c in tcpConnections)
{
TcpState stateOfConnection = c.State;
if (c.LocalEndPoint.Equals(ClientSocket.Client.LocalEndPoint) && c.RemoteEndPoint.Equals(ClientSocket.Client.RemoteEndPoint))
{
if (stateOfConnection == TcpState.Established)
{
return true;
}
else
{
return false;
}
}
}
return false;
}
謝謝,它解決了我的問題。 – Pratikk 2015-12-01 11:55:10
在我的情況,我被髮送一些命令到服務器(在同一計算機上的虛擬機上運行),並等待響應。但是,如果服務器在等待時意外停止,我沒有收到任何通知。我嘗試了其他海報提出的可能性,但都沒有工作(它總是說服務器仍然連接)。對於我來說,這是工作的唯一的事情就是寫0字節流:
var client = new TcpClient();
//... open the client
var stream = client.GetStream();
//... send something to the client
byte[] empty = { 0 };
//wait for response from server
while (client.Available == 0)
{
//throws a SocketException if the connection is closed by the server
stream.Write(empty, 0, 0);
Thread.Sleep(10);
}
彼得Wone的解決方案和烏列是非常好的。但是您還需要檢查遠程端點,因爲您可以有多個到您的本地端點的開放連接。
public static TcpState GetState(this TcpClient tcpClient)
{
var foo = IPGlobalProperties.GetIPGlobalProperties()
.GetActiveTcpConnections()
.SingleOrDefault(x => x.LocalEndPoint.Equals(tcpClient.Client.LocalEndPoint)
&& x.RemoteEndPoint.Equals(tcpClient.Client.RemoteEndPoint)
);
return foo != null ? foo.State : TcpState.Unknown;
}
是的。套接字層應使用異常進行管理。拋出的IOException將內部異常設置爲SocketException,其中包含遠程檢測超時或關閉套接字所需的所有信息。 – Luca 2010-08-26 09:14:52