Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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#_Sockets_Tcp - Fatal编程技术网

套接字保持活动扩展是如何工作的?C#

套接字保持活动扩展是如何工作的?C#,c#,sockets,tcp,C#,Sockets,Tcp,在编写Socket客户端/服务器的代码时,我曾想过实现HeartBeat以了解客户端是否处于活动状态,但随后搜索了其他方法,发现了这段代码,它似乎与描述中的完全相同: public static class SocketExtensions { /// <summary> /// A structure used by SetKeepAliveEx Method /// </summary> [StructLayout(Layout

在编写Socket客户端/服务器的代码时,我曾想过实现HeartBeat以了解客户端是否处于活动状态,但随后搜索了其他方法,发现了这段代码,它似乎与描述中的完全相同:

public static class SocketExtensions
{
    /// <summary>
    ///     A structure used by SetKeepAliveEx Method
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal struct TcpKeepAlive
    {
        internal uint onoff;
        internal uint keepalivetime;
        internal uint keepaliveinterval;
    };

    /// <summary>
    ///     Sets the Keep-Alive values for the current tcp connection
    /// </summary>
    /// <param name="socket">Current socket instance</param>
    /// <param name="keepAliveInterval">Specifies how often TCP repeats keep-alive transmissions when no response is received. TCP sends keep-alive transmissions to verify that idle connections are still active. This prevents TCP from inadvertently disconnecting active lines.</param>
    /// <param name="keepAliveTime">Specifies how often TCP sends keep-alive transmissions. TCP sends keep-alive transmissions to verify that an idle connection is still active. This entry is used when the remote system is responding to TCP. Otherwise, the interval between transmissions is determined by the value of the keepAliveInterval entry.</param>
    public static void SetKeepAliveEx(this Socket socket, uint keepAliveInterval, uint keepAliveTime)
    {
        var keepAlive = new TcpKeepAlive
        {
            onoff = 1,
            keepaliveinterval = keepAliveInterval,
            keepalivetime = keepAliveTime
        };
        int size = Marshal.SizeOf(keepAlive);
        IntPtr keepAlivePtr = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(keepAlive, keepAlivePtr, true);
        var buffer = new byte[size];
        Marshal.Copy(keepAlivePtr, buffer, 0, size);
        Marshal.FreeHGlobal(keepAlivePtr);
        socket.IOControl(IOControlCode.KeepAliveValues, buffer, null);
    }
}
公共静态类SocketExtensions
{
/// 
///SetKeepAliveEx方法使用的结构
/// 
[StructLayout(LayoutKind.Sequential)]
内部结构TcpKeepAlive
{
内部单元接通断开;
内部uint保持更新时间;
内部uint保持间隔;
};
/// 
///设置当前tcp连接的保持活动状态值
/// 
///当前套接字实例
///指定在未收到响应时TCP重复保持活动状态传输的频率。TCP发送保持活动状态传输以验证空闲连接是否仍处于活动状态。这可防止TCP无意中断开活动线路的连接。
///指定TCP发送保持活动状态传输的频率。TCP发送保持活动状态传输以验证空闲连接是否仍处于活动状态。远程系统响应TCP时使用此项。否则,传输之间的间隔由keepAliveInterval项的值确定。
公共静态void SetKeepAliveEx(此套接字、uint keepAliveInterval、uint keepAliveTime)
{
var keepAlive=新的TcpKeepAlive
{
onoff=1,
keepaliveinterval=keepaliveinterval,
keepalivetime=keepalivetime
};
int size=Marshal.SizeOf(keepAlive);
IntPtr keepAlivePtr=Marshal.AllocHGlobal(大小);
StructureToPtr(keepAlive,keepAlivePtr,true);
var buffer=新字节[大小];
封送处理副本(keepAlivePtr,缓冲区,0,大小);
弗里赫全球元帅(keepAlivePtr);
IOControl(IOControlCode.KeepAliveValues,buffer,null);
}
}
它似乎以一种比实现心跳更简单的方式完成这项工作,尽管我不太了解它是如何工作的,但它似乎是在用非托管代码做一些事情?如果是,为什么


请解释,谢谢

KeepAlive是TCP协议的一部分。通过启用KeepAlive,操作系统将定期向另一方发送空数据包并等待确认。如果在所需的超时时间内未收到ACK,则假定连接已断开,并且可以通知应用程序

然而,通常不需要KeepAlive,除非您有一个只接收的套接字,或者您的连接将长时间处于空闲状态

在仅接收套接字中,您不发送任何数据,因此检测断开连接的唯一方法是发送空数据包并等待确认

如果您有一个双向套接字,那么每次向另一方发送数据时,您实际上也在检查连接是否已断开,因此不需要KeepAlive。请注意,如果您发送数据只是为了响应发送数据的另一端,那么您仍然需要KeepAlive,因为您可能永远无法到达协议的“发送”部分


此外,正如Remy Lebeau在他的评论中所指出的,一个可以长时间空闲的连接可能需要KeepAlive,因为一些路由器/防火墙会在一段时间后关闭空闲连接。

“但是,只有当您有一个只接收套接字时才需要KeepAlive”-这不是真的。使用Keepalive还有其他原因,例如在连接将长时间处于空闲状态时保持连接处于活动状态(请考虑在数据连接上进行长时间传输期间处于空闲状态的FTP命令连接)。有些路由器/防火墙会在一段时间后关闭空闲连接,所以可以使用Keepalive来解决这个问题。@RemyLebeau:你说得对,谢谢你提出这个问题。我已经编辑了我的答案以确保完整性