简体   繁体   English

网络适​​配器关闭时检测客户端断开连接

[英]Detect client disconnect when network adapter was turned off

I have trouble with detecting client disconnect from host.我无法检测客户端与主机的断开连接。 Currently my code looks like this:目前我的代码是这样的:

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);

And the IsConnected() extension: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;
  }
 }
}

Works when I close the application, but not when I turn off the network card.关闭应用程序时有效,但关闭网卡时无效。 I'm testing this on Debian virtual machines running on VirtualBox.我正在 VirtualBox 上运行的 Debian 虚拟机上对此进行测试。 Is there any way to detect disconnection in this case?在这种情况下,有没有办法检测断开连接?

Works when I close the application, but not when I turn off the network card.关闭应用程序时有效,但关闭网卡时无效。

Turning off the network card is actually not a disconnect.关掉网卡其实不是断网。 If the network card is turned on again the existing connection can continue (providing the interface has still the same IP address) - this is not unusual for example when suspending a laptop and resuming it later.如果再次打开网卡,现有连接可以继续(假设接口仍然具有相同的 IP 地址) - 这在暂停笔记本电脑并稍后恢复时很常见。

With TCP a real disconnect is only an explicit disconnect (FIN gets send) which is done when explicitly closing the socket or which gets implicitly done by the OS kernel on application exit or when the application crashes.对于 TCP,真正的断开连接只是显式断开连接(FIN 被发送),它在显式关闭套接字时完成,或者在应用程序退出或应用程序崩溃时由操作系统内核隐式完成。

What you instead ask for is not an explicit disconnect but to detect if the peer is currently not reachable, like when the line is (temporarily) disconnected or the system has crashed.相反,您要求的不是显式断开连接,而是检测当前是否无法访问对等方,例如线路(临时)断开连接或系统崩溃时。 This can be done by having some kind of heartbeat either at the application level or at the TCP level.这可以通过在应用程序级别或 TCP 级别使用某种心跳来完成。 The latter is called TCP keep alive and works by sending empty TCP packets and check if an ACK is sent back.后者称为 TCP 保持活动,通过发送空 TCP 数据包并检查是否发回 ACK 来工作。 See here for an example on how to use this.有关如何使用它的示例,请参见此处

I have similary problem, when i want to know if my network interface is known or not我有类似的问题,当我想知道我的网络接口是否已知时

i am using this piece of code to check the different network interfaces:我正在使用这段代码来检查不同的网络接口:

file NetworkMonitor.cs文件 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;
            }
        }
    }
}

you could use these files like this for example:您可以像这样使用这些文件,例如:

    private NetworkAdapter[] adapters;
    private NetworkMonitor monitor;   

you trap the list of network devices, so you could check if your prefered network device is known or unknown您捕获网络设备列表,因此您可以检查您的首选网络设备是已知还是未知

    monitor =   new NetworkMonitor();
    this.adapters   =   monitor.Adapters;

If you want you could measure the speed of download and/or upload if you want..如果你愿意,你可以测量下载和/或上传的速度。

following the version of framework you have to included in the exe.config file this piece of code :(to avoid the error -> InvalidOperation : Instance 'XXX' does not exist in the specified Category)遵循框架的版本,您必须在 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.

相关问题 检测WLAN是否关闭 - detect if wlan is turned off 检测客户端与 HttpListener 断开连接 - Detect client disconnect with HttpListener 如何在网络电缆断开网络适配器时获取套接字的状态 - How to get status of socket when network cable disconnect from network adapter 如何在Windows 7 / Vista中检测.NET Framework功能何时“关闭”? - How can I detect when the .NET Framework feature is “turned off” in Windows 7 / Vista? 尝试让广播接收器检测我何时更改网络或与之断开连接 - Trying to make a broadcast receiver to detect when i change network or disconnect from one TcpListener:如何检测客户端断开连接? - TcpListener: How can I detect a client disconnect? UAC关闭时如何提升应用程序? - How to elevate application when UAC is turned Off? 如何检测WCF服务关闭或断开与客户端的连接? - how to detect WCF service shutdown or disconnect from client? 在 Unity(镜像)中拍摄时客户端断开连接 - Client disconnect when shooting in Unity (Mirror) C#:查明蓝牙适配器是否打开/关闭+所用堆栈的类型(以编程方式) - C#: Find out if the Bluetooth adapter is turned On/Off + the type of the STACK used (Programmatically)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM