创建线程、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;
相关推荐
我在人间贩卖青春4 天前
多路复用select函数
select·多路复用
Trouvaille ~6 天前
【Linux】select 多路转接深度剖析:从位图原理到字典服务器实现
linux·运维·服务器·c++·select·多路转接·io模型
Trouvaille ~6 天前
【Linux】poll 多路转接:select 的改良版,以及它留下的遗憾
linux·运维·服务器·操作系统·select·poll·多路复用
xu_yule23 天前
网络和Linux网络-13(高级IO+多路转接)五种IO模型+select编程
linux·网络·c++·select·i/o
hjjdebug1 个月前
select 函数详解
select·c 语言
曲幽1 个月前
告别重复劳动:SQL Server存储过程实战手册,从入门到高效协作
sql·select·cursor·declare·trigger·procedure
源代码•宸1 个月前
Golang原理剖析(channel面试与分析)
开发语言·经验分享·后端·面试·golang·select·channel
源代码•宸1 个月前
Golang原理剖析(channel源码分析)
开发语言·后端·golang·select·channel·hchan·sudog
源代码•宸1 个月前
Golang语法进阶(Sync、Select)
开发语言·经验分享·后端·算法·golang·select·pool
Ronin3052 个月前
【Linux网络】多路转接select
linux·网络·select·多路转接