简体   繁体   English

如何检测断开连接的套接字C#?

[英]How to detect a disconnected socket C#?

I've been working on a socket client program in C# and am wondering how to detect when the other end of a socket has disconnected itself "ungracefully" as in a network cable being unplugged or a hard reset. 我一直在使用C#中的套接字客户端程序,并且想知道如何检测套接字的另一端何时“不正常”地断开连接,就像拔出网络电缆或硬重置一样。

I have these functions below to access the socket and according to the SO question here and this MSDN article , the best way to check for a disconnected socket is to send a 1-byte message with a length of 0. If an exception is thrown and WSAEWOULDBLOCK is not the error code then the socket is disconnected. 我在下面有这些函数来访问套接字,根据这里的SO问题和这篇MSDN文章 ,检查断开连接套接字的最佳方法是发送长度为0的1字节消息。如果抛出异常并且WSAEWOULDBLOCK不是错误代码,然后套接字断开连接。 I have tried this but after hard reseting the server connection the client will call Send(new byte[1], 0, 0, SocketFlags.None) and return successfully and the Receive() command right afterwards returns the WSAEWOULDBLOCK error. 我试过这个但是在硬重置服务器连接之后,客户端将调用Send(new byte[1], 0, 0, SocketFlags.None)并成功返回并且之后的Receive()命令返回WSAEWOULDBLOCK错误。

What gives?? 是什么赋予了??

Here's my code below. 这是我下面的代码。 _socket is set to non-blocking mode: _socket设置为非阻塞模式:

private int nonBlockRecv(byte[] recvBytes, int offset, int size, SocketFlags sf)
{
    int bytesRecv = 0;

    while (true)
    {
        try
        {
            nonBlockSend(new byte[1], 0, 0, sf);
            bytesRecv = _socket.Receive(recvBytes, offset, size, sf);
            break;
        }
        catch (SocketException excp)
        {
            if (excp.ErrorCode != 10035) // WSAEWOULDBLOCK
                throw excp;
        }
    }

    return bytesRecv;
}

private int nonBlockSend(byte[] sendBytes, int offset, int size, SocketFlags sf)
{
    int bytesSent = 0;

    while (true)
    {
        try
        {
            _socket.Send(sendBytes, offset, size, sf);
            break;
        }
        catch (SocketException excp)
        {
            if (excp.ErrorCode != 10035) // WSAEWOULDBLOCK
                throw excp;
        }
    }

    return bytesSent;
}

Edit: This may be beneficial but the server is Windows Mobile device. 编辑:这可能是有益的,但服务器是Windows Mobile设备。 I read in another thread that different OSs maybe able to send socket close signals when they're dying. 我在另一个线程中读到,不同的OS可能会在它们死亡时发送套接字关闭信号。 Perhaps the Windows Mobile OS does not do this?? 也许Windows Mobile OS不这样做?

If the remote computer gracefully disconnects the session, the Socket.Receive() method will return with 0 bytes. 如果远程计算机正常断开会话连接, Socket.Receive()方法将返回0字节。 You must detect that to know that the remote end has disconnected: 您必须检测到该信息才能知道远程端已断开连接:

int recv = sock.Receive(data);
if (recv == 0)
{
    // Remote client has disconnected.
}
else
{
    // Remote client has sent data.
}

Also, even if there SocketException arises you can identify the exception for socket disconnection. 此外,即使出现SocketException ,您也可以识别套接字断开的异常。

Hope this helps solve your problem. 希望这有助于解决您的问题。

I know this is late but I came up with a cunning solution for this. 我知道这已经晚了但我想出了一个狡猾的解决方案。

I had to communicate with 3rd party software which expected a carriage return on every command sent, otherwise it ignored it. 我不得不与第三方软件进行通信,该软件期望在发送的每个命令上都有回车符,否则它会忽略它。

During the main phase my client socket was in a loop receiving responses from the 3rd party software. 在主要阶段,我的客户端套接字处于循环中,接收来自第三方软件的响应。 My solution isn't ideal but the basic premise is that I put a receive timeout on the socket so that the loop will try to read for 5 seconds then fall into the catch, then loop again. 我的解决方案并不理想,但基本前提是我在套接字上设置接收超时,以便循环尝试读取5秒然后落入catch,然后再循环。 Before each receive I call my own isconnected method which performs a small write without a carriage return, so it's ignored by the 3rd party software yet will give me a reliable fallover if the network has dropped. 在每次接收之前,我调用我自己的isconnected方法,它执行一个没有回车的小写,所以它被第三方软件忽略,但如果网络丢失,它将给我一个可靠的失败。 All I do if the write fails is throw a LostConnectionException and handle that externally. 如果写入失败,我所做的就是抛出一个LostConnectionException并在外部处理它。

If you are writing both server and client, you can quite easily come up with some checkdigit that the other ignores. 如果您同时编写服务器和客户端,则可以很容易地提出另一个忽略的checkdigit。

This may not be perfect but it's reliable for me. 这可能不完美但对我来说可靠。

while (numberOfBytesRead == 0)
{          
    try
    {
        IsConnected();
        _socket.ReceiveTimeout = 5000;
        numberOfBytesRead = _socket.Receive(myReadBuffer, 0, myReadBuffer.Length, SocketFlags.None);

    }
    catch (Exception e)
    {
        if (e.GetType() == typeof (LostConnection))
        {
            Status = SocketStatus.offline;
            throw;
        }
    }
}

and the isconnected method would look something like this 并且isconnected方法看起来像这样

public bool IsConnected(Socket s)
{
    try
    {
        ASCIIEncoding encoder = new ASCIIEncoding();
        byte[] buffer = encoder.GetBytes("test");
        s.Send(buffer, 0, buffer.Length, SocketFlags.None);
    }
    catch (Exception)
    {
        throw new LostConnection();
    }
    return s.Connected;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM