首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >即时检测客户端与服务器插座的断开连接

即时检测客户端与服务器插座的断开连接
EN

Stack Overflow用户
提问于 2009-04-06 16:38:40
回答 15查看 175.2K关注 0票数 87

如何检测客户端是否已与服务器断开连接?

我的AcceptCallBack方法中有以下代码

static Socket handler = null;
public static void AcceptCallback(IAsyncResult ar)
{
  //Accept incoming connection
  Socket listener = (Socket)ar.AsyncState;
  handler = listener.EndAccept(ar);
}

我需要找到一种方法来尽快发现客户端已从handler套接字断开连接。

我试过了:

  1. handler.Available;
  2. handler.Send(new byte[1], 0, SocketFlags.None);
  3. handler.Receive(new byte[1], 0, SocketFlags.None);

当您连接到服务器并想要检测服务器何时断开连接时,上述方法有效,但当您是服务器并想要检测客户端断开时,它们不起作用。

任何帮助都将不胜感激。

EN

回答 15

Stack Overflow用户

回答已采纳

发布于 2009-04-06 16:46:23

由于没有事件可以在套接字断开连接时发出信号,因此您必须以您可以接受的频率轮询它。

使用此扩展方法,您可以有一个可靠的方法来检测套接字是否断开连接。

static class SocketExtensions
{
  public static bool IsConnected(this Socket socket)
  {
    try
    {
      return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
    }
    catch (SocketException) { return false; }
  }
}
票数 121
EN

Stack Overflow用户

发布于 2015-08-27 16:42:47

有人提到了TCP Socket的keepAlive功能。这里有一个很好的描述:

http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html

我是这样使用它的:连接套接字后,我调用此函数,该函数将keepAlive设置为on。keepAliveTime参数指定在发送第一个保活数据包之前没有任何活动的超时时间(毫秒)。keepAliveInterval参数指定在未收到确认的情况下连续发送保活数据包的时间间隔(毫秒)。

    void SetKeepAlive(bool on, uint keepAliveTime, uint keepAliveInterval)
    {
        int size = Marshal.SizeOf(new uint());

        var inOptionValues = new byte[size * 3];

        BitConverter.GetBytes((uint)(on ? 1 : 0)).CopyTo(inOptionValues, 0);
        BitConverter.GetBytes((uint)keepAliveTime).CopyTo(inOptionValues, size);
        BitConverter.GetBytes((uint)keepAliveInterval).CopyTo(inOptionValues, size * 2);

        socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
    }

我还使用了异步读取:

socket.BeginReceive(packet.dataBuffer, 0, 128,
                    SocketFlags.None, new AsyncCallback(OnDataReceived), packet);

在回调中,这里是捕获的超时SocketException,当socket在keep-alive数据包之后没有收到确认信号时引发。

public void OnDataReceived(IAsyncResult asyn)
{
    try
    {
        SocketPacket theSockId = (SocketPacket)asyn.AsyncState;

        int iRx = socket.EndReceive(asyn);
    }
    catch (SocketException ex)
    {
        SocketExceptionCaught(ex);
    }
}

这样,我就能够安全地检测到TCP客户端和服务器之间的连接断开。

票数 28
EN

Stack Overflow用户

发布于 2009-04-06 16:45:54

这根本是不可能的。您和服务器之间没有物理连接(除非在极少数情况下,您使用环回电缆在两台计算机之间连接)。

当连接正常关闭时,另一端会收到通知。但是如果连接是以其他方式断开的(比如用户连接断开),那么服务器直到超时才会知道(或者尝试写入连接,然后ack超时)。这就是TCP的工作方式,您必须接受它。

因此,“即时”是不现实的。您能做的最好的事情就是在超时时间内完成,这取决于运行代码的平台。

编辑:如果你只是在寻找优雅的连接,那么为什么不从你的客户端向服务器发送一个“断开”命令呢?

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/722240

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档