创建线程、socket通信、recv非阻塞

1、线程、及设置线程优先级

cpp 复制代码
mhndMutex = CreateMutex(NULL, FALSE, NULL);
mhndRcv = CreateThread(NULL, 0, &ReceiveData, this, 0, NULL);
CheckPtr_NULL(mhndRcv);
SetThreadPriority(mhndRcv, THREAD_PRIORITY_NORMAL);

mhndDraw = CreateThread(NULL, 0, &DrawDcAmp, this, 0, NULL);
CheckPtr_NULL(mhndDraw);
SetThreadPriority(mhndDraw, THREAD_PRIORITY_BELOW_NORMAL);

2、线程内部函数(静态成员函数)

cpp 复制代码
DWORD MyClient::ReceiveData(LPVOID lpParam)
{
    MyClient* pClient = (MyClient*)lpParam;
    CheckPtr_NULL_Re0(pClient);
    WORD sockVersion = MAKEWORD(2, 2);
    WSADATA data;
    if (WSAStartup(sockVersion, &data) != 0)
    {
        return 0;
    }

    SOCKET sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sockfd == INVALID_SOCKET)
    {
        AfxMessageBox(_T("建立通信失败,请重试!"));
        WSACleanup();
        return 0;
    }

    struct sockaddr_in serAddr;
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(gpServerDB.GetDatalPort());
    char strIP[16];
    DWORD dwIp = gpServerDB.GetIP();
    unsigned char* nIP = (unsigned char*)&dwIp;
    sprintf_s(strIP, "%d.%d.%d.%d", nIP[3], nIP[2], nIP[1], nIP[0]);
    inet_pton(AF_INET, strIP, &(serAddr.sin_addr.S_un.S_addr));
    if (connect(sockfd, (struct sockaddr*)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
    {
        AfxMessageBox(_T("连接失败,请重试!"));
        closesocket(sockfd);
        WSACleanup();
        return 0;
    }
    u_long nonBlocking = 1;
    if (ioctlsocket(sockfd, FIONBIO, &nonBlocking) == SOCKET_ERROR) 
    {
        std::cerr << "设置套接字为非阻塞模式失败" << std::endl;
        closesocket(sockfd);
        WSACleanup();
        return 0;
    }

    gpServerFile.FamesByteFile_Create();

    char recData[MC_FramesDataLenMax * 2];
    memset(recData, '\0', sizeof(recData));
    int nRemindChar = 0;
    int nTotalDataCount = 0;
    int nTotalData = gpServerDB.GetScanTime() * 10 * MC_FramesLen;

    fd_set readfds, writefds, exceptfds;
    int maxfd = static_cast<int>(sockfd);
    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);

    while (pClient->m_bRunning)
    {
        if (nTotalData == nTotalDataCount)
        {
            pClient->BFinished(nTotalData, nTotalDataCount);
            break;
        }

        struct timeval timeout {0,200};
        fd_set tempReadfds = readfds;
        int ret = select(maxfd + 1, &tempReadfds, &writefds, &exceptfds, &timeout);
        if (ret == -1)
        {
            //DebugStr(_T("select -1"));
            break;
        }
        else if (ret == 0)
        {
            //DebugStr(_T("over time"));
            continue;
        }
        if (!FD_ISSET(sockfd, &readfds)) 
            break;

        stTcpFrames stFrame;

        char recDataRes[MC_FramesDataLenMax];

        stFrame.mnRecvLen = recv(sockfd, recDataRes, MC_FramesDataLenMax, 0);
        // 没有数据可读,继续循环检查
        if (WSAGetLastError() == WSAEWOULDBLOCK) 
        {
            if (!pClient->m_bRunning)
                break;
            continue;
        }
        // 服务器关闭了连接"
        else if (stFrame.mnRecvLen == 0)
        {
            break;
        }
        else
        {
            pClient->mbProgressBarStart = true;
            /*DebugStr(_T("recv ok"));
            CString strTip;strTip.Format(_T("%d"), pClient->m_bRunning);DebugStrTip();*/
        }

      /* 数据集解析*/
        // ........................
    }
    pClient->BFinished(0,0);
    gpServerFile.File_Close(enFileType_FamesByte);

    if (sockfd != INVALID_SOCKET)
    {
        closesocket(sockfd);
        WSACleanup();
    }
    return 0;
}
cpp 复制代码
DWORD MyClient::DrawDcAmp(LPVOID lpParam)
{
    MyClient* pClient = (MyClient*)lpParam;
    CheckPtr_NULL_Re0(pClient);
    while (pClient->m_bRunning )
    {
        WaitForSingleObject(pClient->mhndMutex, INFINITE);
        if (pClient->m_bRecvFinish)
        {
            ReleaseMutex(pClient->mhndMutex);
            break;
        }
        pClient->OnDataPackageReceived();
        for (int i = 0; i < pClient->mVctCell.size();i++)
        {
            stDataCell stDataCellFrame = pClient->mVctCell[i];
            pClient->OnDataReceived(stDataCellFrame.dc.f, stDataCellFrame.amp.f);
        }
        pClient->mVctCell.clear();

        ReleaseMutex(pClient->mhndMutex);
    }
    return 0;
}

3、线程退出

cpp 复制代码
Setm_bRunning(FALSE);

if (mhndRcv != NULL)
{
    WaitForSingleObject(mhndRcv, INFINITE);
    CloseHandle(mhndRcv);
    mhndRcv = NULL;
}
if (mhndDraw != NULL)
{
    WaitForSingleObject(mhndDraw, INFINITE);
    CloseHandle(mhndDraw);
    mhndDraw = NULL;
}
m_vctReciveData.clear();
mVctCell.clear();
m_bRecvFinish = false;
mbProgressBarStart = false;
mbErpcSet = false;
相关推荐
IF YOU~3 天前
vue element 切换 select 下拉框的 单选多选报错
vue.js·select
Peter_chq18 天前
【计算机网络】多路转接之select
linux·c语言·开发语言·网络·c++·后端·select
橘色的喵1 个月前
C++编程:嵌入式Linux-ARM与外设中断交互的程序设计
linux·arm开发·select·interrupt·中断·低延迟·设备交互
hope_wisdom1 个月前
C++网络编程之IO多路复用(一)
网络·c++·select·io多路复用
健飞5 个月前
鸿蒙(HarmonyOS)下拉选择控件
华为·select·harmonyos·鸿蒙系统·下拉选择
applebomb5 个月前
简化mybatis @Select IN条件的编写
windows·select·mybatis·jpa·annotation
图图淘气5 个月前
sql常见50道查询练习题
数据库·sql·select
rex0y6 个月前
基于mybatis plus增加较复杂自定义查询以及分页
java·select·mybatis·关联查询·分页·page·属性条件
linux大本营6 个月前
图解通用网络IO底层原理、Socket、epoll、用户态内核态······
linux·网络·select·socket·epoll