Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在C语言中检测套接字断开#_C#_Sockets_Tcpclient_Streamwriter - Fatal编程技术网

C# 如何在C语言中检测套接字断开#

C# 如何在C语言中检测套接字断开#,c#,sockets,tcpclient,streamwriter,C#,Sockets,Tcpclient,Streamwriter,我正在处理一种客户机/服务器关系,这种关系意味着在不确定的时间内来回推送数据 我试图克服的问题是在客户端,因为我无法找到检测断开连接的方法 我在其他人的解决方案中也做过几次尝试,从捕获IO异常到在所有三种模式下轮询套接字。我还尝试使用民意调查的组合,检查套接字的“可用”字段 // Something like this Boolean IsConnected() { try { bool part1 = this.Connection.Client.Poll(10

我正在处理一种客户机/服务器关系,这种关系意味着在不确定的时间内来回推送数据

我试图克服的问题是在客户端,因为我无法找到检测断开连接的方法

我在其他人的解决方案中也做过几次尝试,从捕获IO异常到在所有三种模式下轮询套接字。我还尝试使用民意调查的组合,检查套接字的“可用”字段

// Something like this
Boolean IsConnected()
{
    try
    {
        bool part1 = this.Connection.Client.Poll(1000, SelectMode.SelectRead);
        bool part2 = (this.Connection.Client.Available == 0);

        if (part1 & part2)
        {
            // Never Occurs
            //connection is closed
            return false;
        }
        return true;
    }
    catch( IOException e )
    {
        // Never Occurs Either
    }
}
在服务器端,尝试向客户端写入“空”字符(\0)将强制执行IO异常,服务器可以检测到客户端已断开连接(非常简单的gig)

在客户端,相同的操作不会产生异常

// Something like this
Boolean IsConnected( )
{
    try
    {

        this.WriteHandle.WriteLine("\0");
        this.WriteHandle.Flush();
        return true;
    }
    catch( IOException e )
    {
        // Never occurs
        this.OnClosed("Yo socket sux");
        return false;
    }
}
我相信我在通过轮询检测断开连接时遇到的一个问题是,如果我的服务器自上次检查以来还没有将任何内容写回客户端,我很容易在SelectRead上遇到false。。。我不知道该怎么做,我已经找到了每一个选项来进行检测,我可以找到,但没有什么是100%适合我的,最终我的目标是检测服务器(或连接)故障,通知客户端,等待重新连接,等等。所以我相信你可以想象这是一个完整的部分

感谢任何人的建议。 提前谢谢


编辑:任何查看此问题的人都应该注意下面的答案,以及我对它的最后评论。我已经详细阐述了我是如何克服这个问题的,但还没有发表“Q&a”风格的帖子。

一个选择是使用TCP保持活动数据包。通过调用
Socket.IOControl()
打开它们。唯一令人恼火的是,它需要一个字节数组作为输入,所以您必须将数据转换为一个字节数组才能传入。下面是一个使用10000ms保持活动并重试1000ms的示例:

Socket socket; //Make a good socket before calling the rest of the code.
int size = sizeof(UInt32);
UInt32 on = 1;
UInt32 keepAliveInterval = 10000; //Send a packet once every 10 seconds.
UInt32 retryInterval = 1000; //If no response, resend every second.
byte[] inArray = new byte[size * 3];
Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size);
Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size);
Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size);
socket.IOControl(IOControlCode.KeepAliveValues, inArray, null);

仅当您不发送其他数据时,才会发送保持活动状态的数据包,因此每次发送数据时,10000ms计时器都会重置。

只需捕获IOExceptions,并使用读取超时即可。你不需要所有其他的胡言乱语。我已经试过了(万一你没有真正读过我的帖子…),而且是成功还是失败。一秒钟后读取操作超时会导致IO,这将强制断开连接。。。但是如果我没有收到数据呢…?我读了你的帖子。它不是“命中即失”,它受到本地和远程异步数据缓冲的影响。在对失败连接的第一次写入时不会出现异常,因为尚未检测到异常:在TCP超时重试尝试后,将在后续写入时出现异常。很抱歉,我强烈反对。如果您希望…Socket.Receive和EndReceive()在远程端关闭时返回零,我可以启动调试会话。API描述中记录了这一点:如果您使用的是面向连接的套接字,Receive方法将读取尽可能多的数据,直到缓冲区的大小。如果远程主机使用Shutdown方法关闭套接字连接,并且所有可用数据都已收到,那么Receive方法将立即完成并返回零字节。太棒了,谢谢Joel,我一定会在点击我的开发系统后立即进行测试。嘿Joel,我想我明白了,但是如果我错了,请纠正我;IOControl方法将“KeepAlive”数据包的定时传递放在套接字上。我向我的SocketServer.Client和SocketClient构造函数中添加了(几乎是逐字逐句)上述代码。我将计时器缩短到了一秒钟(因为这是我两侧“读取”的超时时间?),但是我的StreamReader.ReadLine(当我键入这个时才意识到这不应该是我的策略)从未捕获任何数据。。。我必须说,我不确定我们为什么要把我们要放的东西放进阵列中;我可以终止它吗?实际上,我只是试着用一个StreamReader运行同样的东西。读取调用,但仍然没有在任何方向得到任何东西。可能是因为我不完全理解这个概念。@805-我有理由肯定,在你看到任何东西之前,养活动物已经被吃掉了。要测试它,请在不同的机器上运行应用程序,然后运行wireshark查看数据。您应该看到keep-alive退出并返回一个回复(如果所有内容都已连接),但是您的read()调用将看不到任何内容。@Carlos这是正确的。使用此选项时,无需调用SetSocketOption()。