zoukankan      html  css  js  c++  java
  • Windows 下TCP长连接保持连接状态TCP keepalive设置

    TCP长连接建立完成后,我们通常需要检测网络的连接状态,以反馈给客户做响应的处理。通过设置TCP keepalive的属性,打开socket的keepalive属性,并设置发送底层心跳包的时间间隔。TCP/IP五层网络模型,我们调用socket等接口是应用层的函数,TCP keepalive是在底层定时发送心跳报文,服务器端接收到底层的心跳报文直接丢弃,不关心其内容。

    以下是windows下TCP keepalive设置的函数:

    #include <mstcpip.h>
    int CClientCtrl::socket_tcp_alive(int socket)
    {
        int ret = 0;
    
    
        int keep_alive = 1;
    
        ret = setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&keep_alive, sizeof(keep_alive));
    
    
        if (ret == SOCKET_ERROR)
    
        {
    
            printf("setsockopt failed: %d 
    ", WSAGetLastError());
    
            return -1;
    
        }
    
    
        struct tcp_keepalive in_keep_alive = {0};
    
        unsigned long ul_in_len = sizeof(struct tcp_keepalive);
    
        struct tcp_keepalive out_keep_alive = {0};
    
        unsigned long ul_out_len = sizeof(struct tcp_keepalive);
    
        unsigned long ul_bytes_return = 0;
    
    
        in_keep_alive.onoff = 1; /*打开keepalive*/
    
        in_keep_alive.keepaliveinterval = 5000; /*发送keepalive心跳时间间隔-单位为毫秒*/
    
        in_keep_alive.keepalivetime = 1000; /*多长时间没有报文开始发送keepalive心跳包-单位为毫秒*/
    
    
        ret = WSAIoctl(socket, SIO_KEEPALIVE_VALS, (LPVOID)&in_keep_alive, ul_in_len,
    
            (LPVOID)&out_keep_alive, ul_out_len, &ul_bytes_return, NULL, NULL);
    
    
        if (ret == SOCKET_ERROR)
    
        {
    
            printf("WSAIoctl failed: %d 
    ", WSAGetLastError());
    
            return -1;
    
        }
    
    
        return 0;
    }

    以TCP 客户端为例:

    SHORT CClientCtrl::connetServer(LPCTSTR strAddr,USHORT portNum)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
        // TODO: Add your dispatch handler code here
        m_addr = strAddr;
         USES_CONVERSION;
         char *pCharAddr = T2A(m_addr);
        
        WSADATA wsd;
        WSAStartup(MAKEWORD(2, 2), &wsd);
        m_sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        SOCKADDR_IN  ClientAddr;
    
        ClientAddr.sin_family = AF_INET;
        ClientAddr.sin_addr.S_un.S_addr = inet_addr(pCharAddr);//
        ClientAddr.sin_port = htons(portNum);//m_port
        int n = 0;
        n = connect(m_sockClient, (struct sockaddr*)&ClientAddr, sizeof(ClientAddr));
        if (n == SOCKET_ERROR) {
            
            return -1;
        }
    
        //set keepAlive  
        n = socket_tcp_alive(m_sockClient);//设置keepalive
        if (n <0 )
        {
            return -1;
        }
        
        CreateThread(NULL, 0, &recvFromServer, (LPVOID)this, 0, NULL);
    
        return 0;
    }
    DWORD WINAPI  recvFromServer(LPVOID lpParameter)
    {
        char RecvBuf[MaxBufSize];
        CClientCtrl* pParent = (CClientCtrl*)lpParameter;
        SOCKET *ClientSocket = &(pParent->m_sockClient);
        int iLength;
        while (true) {
            memset(RecvBuf, '', sizeof(RecvBuf));
            iLength = recv(*ClientSocket, RecvBuf, MaxBufSize, 0);
            if (iLength <=0) //error   
            {
    
                strcpy(RecvBuf,"ERROR");
                ::SendMessage(pParent->m_hWnd,WM_RECVMSG,(WPARAM)RecvBuf,0);
    
                break;
            }
            else
            {
                ::SendMessage(pParent->m_hWnd,WM_RECVMSG,(WPARAM)RecvBuf,0);
    
            }
            
    
    
        }
        return 0;
    }

      recv函数的返回值能反应网络的状态;

       iLength = recv(*ClientSocket, RecvBuf, MaxBufSize, 0);

    如果服务器端正常关闭socket ,那么recv 的返回值iLength 为0;这种情况即使不设置keepAlive 也是可以正常返回的;

    如果出现暴力关闭,比如网线被拔,服务器程序强行关闭,recv 的返回值iLength 为-1; 如果不设置keepAlive 的话,这里是不会有任何反应的。 

    参考文献:http://blog.csdn.net/embedded_sky/article/details/42077321

  • 相关阅读:
    168. Excel Sheet Column Title
    171. Excel Sheet Column Number
    264. Ugly Number II java solutions
    152. Maximum Product Subarray java solutions
    309. Best Time to Buy and Sell Stock with Cooldown java solutions
    120. Triangle java solutions
    300. Longest Increasing Subsequence java solutions
    63. Unique Paths II java solutions
    221. Maximal Square java solutions
    279. Perfect Squares java solutions
  • 原文地址:https://www.cnblogs.com/small-lazybee/p/15425091.html
Copyright © 2011-2022 走看看