WINSOCK2 WSAAsyncSelect 已弃用问题

Posted

技术标签:

【中文标题】WINSOCK2 WSAAsyncSelect 已弃用问题【英文标题】:WINSOCK2 WSAAsyncSelect deprecated issue 【发布时间】:2016-06-04 05:48:57 【问题描述】:

您好,我正在使用 winsock2,并且正在尝试进行异步通信。 我尝试使用正在等待接受的TCP server msdn。

我在监听函数之前尝试了WSAAsyncSelect。

WSAAsyncSelect(ListenSocket,
        m_hWnd,
        WM_SOCKET,
        (FD_CLOSE | FD_ACCEPT | FD_READ));

并显示以下错误..

Error   C4996   'WSAAsyncSelect': Use WSAEventSelect() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings 

我该如何解决这个..提前谢谢..

【问题讨论】:

您是否尝试过按照错误消息的提示进行操作? IE。查看WSAEventSelect 函数? @JoachimPileborg 是的,现在我正在研究它.. 只是想知道我可以使用WSAAsyncSelect 的任何方式。 bcz 我有一个示例 pgm fr .. 那么错误信息也会告诉你怎么做。 @JoachimPileborg 我在 winsock2 标头之后尝试了定义。 .现在它正在工作(y) 【参考方案1】:

要消除该警告,您可以在源文件顶部定义 #define _WINSOCK_DEPRECATED_NO_WARNINGS ,这将禁用此类警告。

也就是说,听一下这个警告并改用WSAEventSelect 可能是值得的。 由于WSAEventSelect 发出事件信号,而不是像WSAAsyncSelect 那样将消息发布到Window 的消息队列中。发布到消息队列中的速度较慢,并且会添加实际上并不需要的额外处理。

我有一个示例,我将在这里为您发布: ...我可能已经过火了...但这一切都很有用且相关。

设置监听套接字

if ( socket_name == INVALID_SOCKET )

    P_ERR( "Could not create socket ( Id: %d ): %d\n", id, WSAGetLastError() );
    return INVALID_SOCKET;


rerror = bind( socket_name, (SOCKADDR*)&sock_addr, sizeof( sock_addr ) );
if ( rerror != SOCKET_ERROR )

    rerror = listen( socket_name, MAX_LISTEN_QUEUE );

    if ( rerror != SOCKET_ERROR )
    
        /* Selects the events that will trigger the `socket_event` windows event. */
        /* socket_event was created using 'CreateEvent( NULL, TRUE, FALSE, NULL );' */
        WSAEventSelect( socket_name, socket_event, FD_ALL_EVENTS );

        if ( !startStatusThread() )
        
            rerror = 1;
            P_ERR( "Status thread failed: %d\n", id );
        
    
    else
    
        P_ERR( "listen() error %d : Error %d\n", id, WSAGetLastError() );
        closesocket( socket_name );
    

else

    P_ERR( "bind() error ( Id: %d ): %d\n", id, WSAGetLastError() );
    closesocket( socket_name );

从 Socket 处理事件

    /* waits 10ms for events in the event array ( in this case just 1 event as socket_event ). */
    rerror = WSAWaitForMultipleEvents( 1, &socket_event, FALSE, 10, FALSE );
    if ( rerror == WSA_WAIT_TIMEOUT )
    
        continue; /* this block of code runs in a while loop. */
    

    index = rerror - WSA_WAIT_EVENT_0; /* get the smallest index of a triggered event */
    if ( rerror != WSA_WAIT_TIMEOUT && rerror != WSA_WAIT_FAILED )
    
        /* returns a list of the events that occured. */
        rerror = WSAEnumNetworkEvents( socket_name, socket_event, &events );
        if ( rerror == SOCKET_ERROR )
        
            P_ERR( "WSAEnumNetworkEvents Error %d: Id: %d\n", WSAGetLastError(), pThis->id );
            continue;
        
        /* look below for this function. */
        handleNetworkEvents( events, index );
    

处理事件。

void
handleNetworkEvents( WSANETWORKEVENTS e, const int socket_index )

    int rerror = 0;
    /* on accept. */
    if ( e.lNetworkEvents & FD_ACCEPT )
    
        if ( e.iErrorCode[FD_ACCEPT_BIT] == 0 )
        
            onAccept();
        
        else
        
            P_ERR( "Unknown network event error %d\n", id );
        
    
    /* on connect */
    if ( e.lNetworkEvents & FD_CONNECT )
    
        if ( e.iErrorCode[FD_CONNECT_BIT] == 0 )
        
            sendRead(); /* send first read request */
        
        else
        
            P_ERR( "Unknown network event error %d\n", id );
        
    
    /* on successful read */
    if ( e.lNetworkEvents & FD_READ )
    
        sendRead(); /* get read data and queue another request. */
        callback( id, inBuffer.buf, lastReadSize ); /* process data. */
    
    /* on close. */
    if ( e.lNetworkEvents & FD_CLOSE )
    
        /* close the current event and make a new one ready for a new connection. */
        onClose( socket_index );
    

【讨论】:

@VivekAnanthan 谢谢,我希望它很有用,我不得不剪掉很多代码以使其足够简单,所以把它作为一个使用示例而不是一个完整的工作示例,你应该做得好。 我没有看到 WSAEventSelect() 对窗口应用程序的兴趣;将 Async 替换为 Event 意味着如果您希望窗口应用程序保持响应,您必须自己管理事件列表,并将消息循环更改为使用 MsgWaitForMultipleEvents() 而不是您正在执行的任何操作(这也意味着,没有 DialogBox( ),所以如果您使用 EndDialog(),您现在也需要更改它...) WSAEventSelect 可能对控制台应用程序有好处(即使这样,在控制台上等待也有其自身的问题),但 Async 绝对是最佳选择窗口应用程序! 嗨@Medinoc,如果您觉得微软犯了一个错误并且您有更好的答案,请随时在此问题中发布答案,以便您可以正确解释推理并举例说明。跨度>

以上是关于WINSOCK2 WSAAsyncSelect 已弃用问题的主要内容,如果未能解决你的问题,请参考以下文章

winsock2:服务器端代码调用`accept()`后如何获取已连接客户端的ipv4/ipv6地址

windows下的IO模型之异步选择(WSAAsyncSelect)模型

WSAAsyncSelect 消息模型

如何使 WSAAsyncSelect 在应用程序控制台中启动?

网络IO模型-异步选择

winsock winsock2 TCP/IP协议 tcpip.sys 网卡驱动 有啥相互关系?