客户端SOCKET心跳包检测

客户端SOCKET心跳包检测

socket 长时间连接我们往往需要心跳包检测,我用计数器的形式做了一个简单的心跳包检测,主要是检测io 如果io超过一定时间全是失败,那么我就可以初步断定这个socket有问题,那么我们就可以断定这个socket死掉了,重新初始化socket变量

定义一个全局变量

SOCKET socketFlag;

定义一个计数器结构体

typedef struct _timePack {
    int send_count;
    int recv_count;
}timePack;

timePack timer;

封装一个socket连接的函数

BOOL initSocket()
{
    socketFlag = socket(
        AF_INET,
        SOCK_STREAM,//决定你是用udp还是tcp
        IPPROTO_IP
    );

    if (socketFlag <= 0)
    {
        CLogFile::WriteLog("创建socket失败");
        return FALSE;
    }

    HOSTENT* hostentInfo = gethostbyname((LPSTR)(LPCSTR)screen_ip);
    if (hostentInfo == 0)
    {
        CLogFile::WriteLog("解析域名失败");
        return FALSE;
    }
    CString strIPAddress;
    strIPAddress.Format(_T("%d.%d.%d.%d"),
        (hostentInfo->h_addr_list[0][0] & 0x00ff),
        (hostentInfo->h_addr_list[0][1] & 0x00ff),
        (hostentInfo->h_addr_list[0][2] & 0x00ff),
        (hostentInfo->h_addr_list[0][3] & 0x00ff));
    SOCKADDR_IN socket_server;
    socket_server.sin_family = AF_INET;
    socket_server.sin_port = htons(8555);
    socket_server.sin_addr.S_un.S_addr = inet_addr(strIPAddress);

    if (int result = connect(socketFlag, (SOCKADDR*)&socket_server, sizeof(SOCKADDR)) == SOCKET_ERROR) {
        CLogFile::WriteLog("连接socket失败");
        return FALSE;
    };

    return TRUE;
}

发送线程检测心跳包代码

////发送线程
void requestFun(SOCKET  socketClient)
{

    while (1)
    {
        MsgWaitForMultipleObjects(1, &hMutex, FALSE, INFINITE, QS_ALLINPUT);

        if (lockDonwload == FALSE) {//如果没有下载
            CCommonFunction commonFunction;
            //获取版本号
            ::GetPrivateProfileString("screen_info", "soft_version", NULL, soft_version.GetBuffer(MAX_PATH), MAX_PATH, commonFunction.GetExecuteAppDir() + "\\download.ini");

            soft_version.ReleaseBuffer();
            if (soft_version.IsEmpty())
            {
                CLogFile::WriteLog("软件版本号不能为空");
                break;
            }
            CString send_info = "download_file|" + screen_id + "|" + soft_version + "&";
            int sendResult = send(socketClient, (PSTR)(PCSTR)send_info, send_info.GetLength(), 0);
            if (sendResult <= 0)
            {
                //由于两个线程两个地址所以不再需要原子操作

                if (timer.send_count >= 5)
                {//连接已经超过事件了需要重新进行socket连接
                    closesocket(socketClient);
                    BOOL initResult = initSocket();
                    if (initResult ==  FALSE)
                    {
                        timer.send_count++;
                        CLogFile::WriteLog("连接服务器失败");
                    }
                    else {
                        timer.send_count = 0;
                        socketClient = socketFlag;
                    }
                }
                else {
                    timer.send_count++;
                    CLogFile::WriteLog("发送失败");
                }
            }else{
                timer.send_count = 0;
            }
            //放锁

            ReleaseMutex(hMutex);
        }
        Sleep(10000);
    }
    return;
}

思路: 写一个计数器结构体,由于客户端是两个线程,所以结构体里放了两个标志位,收发线程的标志位,挂起循环10秒发送一次,如果连续发送失败5次,count到达5,说明50秒了都没有发送成功过,那么久关闭链接重新进行socket初始化,改变全局变量的存放文件描述符的变量,达到一个重新链接的效果

猜你喜欢

转载自blog.csdn.net/qq_32783703/article/details/80339400