创建线程、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;
相关推荐
曲幽2 天前
告别重复劳动:SQL Server存储过程实战手册,从入门到高效协作
sql·select·cursor·declare·trigger·procedure
源代码•宸4 天前
Golang原理剖析(channel面试与分析)
开发语言·经验分享·后端·面试·golang·select·channel
源代码•宸4 天前
Golang原理剖析(channel源码分析)
开发语言·后端·golang·select·channel·hchan·sudog
源代码•宸11 天前
Golang语法进阶(Sync、Select)
开发语言·经验分享·后端·算法·golang·select·pool
Ronin3051 个月前
【Linux网络】多路转接select
linux·网络·select·多路转接
AI2中文网2 个月前
AppInventor2 使用 SQLite(三)带条件过滤查询表数据
数据库·sql·sqlite·select·app inventor 2·appinventor·tableview
无聊的小坏坏2 个月前
Select 服务器实战教学:从 Socket 封装到多客户端并发
服务器·select·io多路复用
Wy_编程4 个月前
高并发服务器-多路IO转接-select
服务器·select·高并发
眰恦ゞLYF5 个月前
服务器类型与TCP并发服务器构建(SELECT)
服务器·select·io多路复用
敲上瘾5 个月前
Linux I/O 多路复用实战:Select/Poll 编程指南
linux·服务器·c语言·c++·select·tcp·poll