WinCE下 WSAWaitForMultipleEvents 事件模型实现并发IO

该博客介绍了如何在WinCE系统中使用WSAWaitForMultipleEvents实现并发IO。通过创建服务器监听套接字、绑定本地地址、设置事件选择和监听事件,展示了如何处理FD_ACCEPT、FD_READ和FD_CLOSE等网络事件,以实现高效的网络通信。
摘要由CSDN通过智能技术生成

直接贴代码

void CListenAction::Init()
{
    // 初始化套接字库
    if (!InitSocketLib())
    {
       TRACE(_T("初始化套接字库失败"));
        return ;
    }

    // 创建服务器端监听套接字
    SOCKET listenSocket;
    listenSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (INVALID_SOCKET == listenSocket)
    {
        TRACE(_T("socket error: %d\n"),WSAGetLastError());
        return;
    }

    // 本地地址
    SOCKADDR_IN localAddr;
    localAddr.sin_family = AF_INET;

    // 获取本机IP地址
    char szIPBuf[100];
    memset(szIPBuf, 0, 100);
    CCommUtility::GetLocalIP(szIPBuf, sizeof(szIPBuf));
    localAddr.sin_addr.S_un.S_addr = inet_addr(szIPBuf);

    // 设置端口号
    localAddr.sin_port = htons(SERVER_PORT);

    INT iRetTmp = bind(listenSocket, (SOCKADDR *)&localAddr, sizeof(localAddr));
    if (SOCKET_ERROR == iRetTmp)
    {
        TRACE(_T("bind error: %d\n"),WSAGetLastError());
        return;
    }

    iRetTmp = listen(listenSocket, LISTEN_QUEUE_LENGTH);
    if (SOCKET_ERROR == iRetTmp)
    {
        TRACE(_T("listen error: %d\n"),WSAGetLastError());
        return;
    }

    // 添加监听主套接字到通信对象数组
    SOCKET_OBJ socketObj;
    socketObj.sd = listenSocket;
    socketObj.emConnectType = LISTEN;
    socketObj.emSocketType = TCP_SOCKET;
    m_arraySocket.Add(socketObj);

    // 添加监听事件到事件数组 关联事件
    WSAEVENT listenEvent = WSACreateEvent();
    int iRet = WSAEventSelect(listenSocket, listenEvent, FD_ACCEPT | FD_CLOSE);
    if (iRet != 0)
   {
       TRACE(_T("WSAEventSelect failed: %d\n"),WSAGetLastError());
       return;
   }
    m_arrayEvent.Add(listenEvent);

    // 开始监听事件
    StartListenEvent();
}

 

/// @brief  开始监听套接字事件
VOID CListenAction::StartListenEvent()
{
    // 网络事件
    WSANETWORKEVENTS netEvents;

    // 返回索引
    DWORD dwIndex = 0;
   
    DWORD dwRetTemp;

    // 循环等待网络事件
    while (TRUE)
    {
        // 判断线程是否退出
        dwRetTemp = WaitForSingleObject(m_ExitEvent.m_hObject, 0);
        if (WAIT_OBJECT_0 == dwRetTemp)
        {
            // 退出
            break;
        }

        // 第一个有事件的通信对象索引
        dwIndex = WSAWaitForMultipleEvents(m_arrayEvent.GetCount(),
                                           &m_arrayEvent[0],
                                           FALSE,
                                           NETWORK_EVENT_WAIT_TIME,
                                           FALSE);
        // 失败
        if (WSA_WAIT_FAILED == dwIndex)
        {
            TRACE(_T("WSAWaitForMultipleEvents error: %d\n"),WSAGetLastError());
            return;
        }
        else
        {
            if (WSA_WAIT_TIMEOUT != dwIndex)
            {
                dwIndex -= WSA_WAIT_EVENT_0;
                for (INT i = dwIndex; i < m_arrayEvent.GetCount(); i++)
                {
                    dwIndex = WSAWaitForMultipleEvents(1, &m_arrayEvent[i], FALSE, 0, FALSE);
                    if ((WSA_WAIT_FAILED != dwIndex) && (WSA_WAIT_TIMEOUT != dwIndex))
                    {
                        /* 枚举通信对象上的事件 */
                        WSAEnumNetworkEvents(m_arraySocket[i].sd, m_arrayEvent[i], &netEvents);
                        if (netEvents.lNetworkEvents & FD_ACCEPT)
                        {
                            if (netEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
                            {
                                TRACE(_T("FD_ACCEPT error: %d\n"),netEvents.iErrorCode[FD_ACCEPT_BIT]);
                                break;
                            }

                            // 接收请求连接的客户端
                            AcceptClientConnection(m_arraySocket[i].sd);
                        }
                        if (netEvents.lNetworkEvents & FD_READ)
                        {
                            if (netEvents.iErrorCode[FD_READ_BIT] != 0)
                            {
                                // 记录日志
                                TRACE(_T("FD_READ error: %d\n"),netEvents.iErrorCode[FD_READ_BIT]);
                                break;
                            }

                            // 报告数据到达事件
                            ReportDataArrive(i);
                        }
                        if (netEvents.lNetworkEvents & FD_CLOSE)
                        {
                            if (netEvents.iErrorCode[FD_READ_BIT] != 0)
                            {
                                // 记录日志
                                TRACE(_T("FD_CLOSE error: %d\n"),netEvents.iErrorCode[FD_CLOSE_BIT]);
                                break;
                            }

                            // 断开连接
                            DisConnect(m_arraySocket[i].sd);
                        }

                    }
     else
     {
      TRACE(_T("WSAWaitForMultipleEvents error: %d\n"),WSAGetLastError());
     }
                }

            }
   else
   {
    TRACE(_T("time out\n"));
   }
        }
    }

}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值