[英]Detect client disconnect when network adapter was turned off
我無法檢測客戶端與主機的斷開連接。 目前我的代碼是這樣的:
Task.Run(() => {
// Create server
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) {
ReceiveTimeout = -1,
};
server.Bind(new IPEndPoint(IPAddress.Any, port));
server.Listen(-1);
// Start listening
while (true) {
Socket socket = server.Accept();
new Thread(() => {
try {
Process(socket);
} catch (Exception ex) {
Trace.WriteLine("Socket connection processing error: " + ex.Message);
}
}).Start();
}
});
// Host client process
void Process(Socket socket) {
byte[] response;
int received;
var ip = IPAddress.Parse(((IPEndPoint) socket.RemoteEndPoint).Address.ToString());
Events.OnNodeConnected(ip);
while (true) {
// Rceive data
response = new byte[socket.ReceiveBufferSize];
received = socket.Receive(response);
// Check connection
if (!socket.IsConnected()) {
socket.Close();
Events.OnNodeDisconnected(ip);
return;
}
try {
// Decode recieved data
List < byte > respBytesList = new List < byte > (response);
和IsConnected()擴展:
public static class SocketExtensions {
public static bool IsConnected(this Socket socket) {
try {
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
} catch (SocketException) {
return false;
}
}
}
關閉應用程序時有效,但關閉網卡時無效。 我正在 VirtualBox 上運行的 Debian 虛擬機上對此進行測試。 在這種情況下,有沒有辦法檢測斷開連接?
關閉應用程序時有效,但關閉網卡時無效。
關掉網卡其實不是斷網。 如果再次打開網卡,現有連接可以繼續(假設接口仍然具有相同的 IP 地址) - 這在暫停筆記本電腦並稍后恢復時很常見。
對於 TCP,真正的斷開連接只是顯式斷開連接(FIN 被發送),它在顯式關閉套接字時完成,或者在應用程序退出或應用程序崩潰時由操作系統內核隱式完成。
相反,您要求的不是顯式斷開連接,而是檢測當前是否無法訪問對等方,例如線路(臨時)斷開連接或系統崩潰時。 這可以通過在應用程序級別或 TCP 級別使用某種心跳來完成。 后者稱為 TCP 保持活動,通過發送空 TCP 數據包並檢查是否發回 ACK 來工作。 有關如何使用它的示例,請參見此處。
我有類似的問題,當我想知道我的網絡接口是否已知時
我正在使用這段代碼來檢查不同的網絡接口:
文件 NetworkMonitor.cs
using System.Collections;
using System.Diagnostics;
using System.Timers;
namespace NetWork.Plus
{
/// <summary>
/// The NetworkMonitor class monitors network speed for each network adapter on the computer,
/// using classes for Performance counter in .NET library.
/// </summary>
public class NetworkMonitor
{
private Timer timer; // The timer event executes every second to refresh the values in adapters.
private ArrayList adapters; // The list of adapters on the computer.
private ArrayList monitoredAdapters; // The list of currently monitored adapters.
public NetworkMonitor()
{
this.adapters = new ArrayList();
this.monitoredAdapters = new ArrayList();
EnumerateNetworkAdapters();
timer = new Timer(1000);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
}
/// <summary>
/// Enumerates network adapters installed on the computer.
/// </summary>
private void EnumerateNetworkAdapters()
{
PerformanceCounterCategory category = new PerformanceCounterCategory("Network Interface");
foreach (string name in category.GetInstanceNames())
{
// This one exists on every computer.
if (name == "MS TCP Loopback interface")
continue;
// Create an instance of NetworkAdapter class, and create performance counters for it.
NetworkAdapter adapter = new NetworkAdapter(name);
adapter.dlCounter = new PerformanceCounter("Network Interface", "Bytes Received/sec", name);
adapter.ulCounter = new PerformanceCounter("Network Interface", "Bytes Sent/sec", name);
this.adapters.Add(adapter); // Add it to ArrayList adapter
}
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
foreach (NetworkAdapter adapter in this.monitoredAdapters)
adapter.refresh();
}
/// <summary>
/// Get instances of NetworkAdapter for installed adapters on this computer.
/// </summary>
public NetworkAdapter[] Adapters
{
get
{
return (NetworkAdapter[])this.adapters.ToArray(typeof(NetworkAdapter));
}
}
// Enable the timer and add all adapters to the monitoredAdapters list, unless the adapters list is empty.
public void StartMonitoring()
{
if (this.adapters.Count > 0)
{
foreach(NetworkAdapter adapter in this.adapters)
if (!this.monitoredAdapters.Contains(adapter))
{
this.monitoredAdapters.Add(adapter);
adapter.init();
}
timer.Enabled = true;
}
}
// Enable the timer, and add the specified adapter to the monitoredAdapters list
public void StartMonitoring(NetworkAdapter adapter)
{
if (!this.monitoredAdapters.Contains(adapter))
{
this.monitoredAdapters.Add(adapter);
adapter.init();
}
timer.Enabled = true;
}
// Disable the timer, and clear the monitoredAdapters list.
public void StopMonitoring()
{
this.monitoredAdapters.Clear();
timer.Enabled = false;
}
// Remove the specified adapter from the monitoredAdapters list, and disable the timer if the monitoredAdapters list is empty.
public void StopMonitoring(NetworkAdapter adapter)
{
if (this.monitoredAdapters.Contains(adapter))
this.monitoredAdapters.Remove(adapter);
if(this.monitoredAdapters.Count == 0)
timer.Enabled = false;
}
}
}
file NetworkAdapter.cs
using System.Diagnostics;
namespace NetWork.Plus
{
/// <summary>
/// Represents a network adapter installed on the machine.
/// Properties of this class can be used to obtain current network speed.
/// </summary>
public class NetworkAdapter
{
/// <summary>
/// Instances of this class are supposed to be created only in an NetworkMonitor.
/// </summary>
internal NetworkAdapter(string name)
{
this.name = name;
}
private long dlSpeed, ulSpeed; // Download\Upload speed in bytes per second.
private long dlValue, ulValue; // Download\Upload counter value in bytes.
private long dlValueOld, ulValueOld; // Download\Upload counter value one second earlier, in bytes.
internal string name; // The name of the adapter.
internal PerformanceCounter dlCounter, ulCounter; // Performance counters to monitor download and upload speed.
/// <summary>
/// Preparations for monitoring.
/// </summary>
internal void init()
{
// Since dlValueOld and ulValueOld are used in method refresh() to calculate network speed, they must have be initialized.
this.dlValueOld = this.dlCounter.NextSample().RawValue;
this.ulValueOld = this.ulCounter.NextSample().RawValue;
}
/// <summary>
/// Obtain new sample from performance counters, and refresh the values saved in dlSpeed, ulSpeed, etc.
/// This method is supposed to be called only in NetworkMonitor, one time every second.
/// </summary>
internal void refresh()
{
this.dlValue = this.dlCounter.NextSample().RawValue;
this.ulValue = this.ulCounter.NextSample().RawValue;
// Calculates download and upload speed.
this.dlSpeed = this.dlValue - this.dlValueOld;
this.ulSpeed = this.ulValue - this.ulValueOld;
this.dlValueOld = this.dlValue;
this.ulValueOld = this.ulValue;
}
/// <summary>
/// Overrides method to return the name of the adapter.
/// </summary>
/// <returns>The name of the adapter.</returns>
public override string ToString()
{
return this.name;
}
/// <summary>
/// The name of the network adapter.
/// </summary>
public string Name
{
get
{
return this.name;
}
}
/// <summary>
/// Current download speed in bytes per second.
/// </summary>
public long DownloadSpeed
{
get
{
return this.dlSpeed;
}
}
/// <summary>
/// Current upload speed in bytes per second.
/// </summary>
public long UploadSpeed
{
get
{
return this.ulSpeed;
}
}
/// <summary>
/// Current download speed in kbytes per second.
/// </summary>
public double DownloadSpeedKbps
{
get
{
return this.dlSpeed/1024.0;
}
}
/// <summary>
/// Current upload speed in kbytes per second.
/// </summary>
public double UploadSpeedKbps
{
get
{
return this.ulSpeed/1024.0;
}
}
}
}
您可以像這樣使用這些文件,例如:
private NetworkAdapter[] adapters;
private NetworkMonitor monitor;
您捕獲網絡設備列表,因此您可以檢查您的首選網絡設備是已知還是未知
monitor = new NetworkMonitor();
this.adapters = monitor.Adapters;
如果你願意,你可以測量下載和/或上傳的速度。
遵循框架的版本,您必須在 exe.config 文件中包含這段代碼:(以避免錯誤 -> InvalidOperation : Instance 'XXX' does not exist in the specified Category)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<settings>
<performanceCounters enabled="true" />
</settings>
</system.net>
</configuration>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.