zoukankan      html  css  js  c++  java
  • Windows异步套接字(WSASocket)

    异步套接字:
    如果使用阻塞的套接字的话,在控制台下还好!如果是WIN32程序的话,那么就容易造成界面的假死,因为接收函数一直等待有消息进来之后才会被返回!所以此时界面一直属于假死的状态,如果你乱动的话,那么就容易真死了。解决办法如下:
    第一:使用多线程技术,多线程和SOCKET结合的话,可以使用单独一个线程来接收消息。这样即使接收函数阻塞了也不会影响其他线程,例如界面线程。但是如果使用多线程的话,就必须要考虑到多线程之间同步的问题,以及临界资源的问题。
     
    第二:使用异步套接字。但是使用异步套接字的话,至少要了解一下Windows的消息机制。异步套接字的工作原理是基于Windows消息的,和在MFC中的其他消息函数一样,当有消息的时候,套接字的相关函数就被触发。例如,我们双击的时候,系统感知了这个消息,然后做出响应。异步套接字的工作也是如此,当有网络消息来的时候,接收函数才工作,否则接收函数是不工作的。
     
    使用步骤如下:
    WSADATA wsaData;
    WORD wVersion = MAKEWORD(2,2);
    //需要打开版本为2.2的socket
    if ( WSAStartup(wVersion,&wsaData) != 0 )
    {
    //打开失败…
    }
    //判断版本是否为2.2
    if ( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) 
    {
    WSACleanup();
    }
     
    //其实代码都是一样的,只是变成了WSA***函数而已!
    SOCKET m_ClientSocket;
    m_ClientSocket = WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,0);
    if ( m_ServerSocket == INVALID_SOCKET )
    {
    MessageBox("创建套接字失败...");
    }
     
    //注册网络事件
    //其实这个函数是关键,首先说一下,最后一个参数是FD_READ其实//还有如下的参数可以填写:
    //Event: FD_ACCEPT
    //Event: FD_ADDRESS_LIST_CHANGE
    //Event: FD_GROUP_QOS
    //Event: FD_OOB
    //Event: FD_QOS
    //Event: FD_READ
    //Event: FD_WRITE
    //这个函数叫注册消息,意思就是如果m_ClientSocket接收到了消息//的话就发送UM_RECVMESSAGE这个消息,为什么是接收到了消息//呢?因为注册的是FD_READ啊,如果注册了FD_ACCEPT那么就是有//人请求连接的时候就发送**消息
    if( SOCKET_ERROR==WSAAsyncSelect(m_ClientSocket,m_hWnd,UM_RECVMESSAGE,FD_READ)  )
    {
    //注册失败.
    }
     
    //接收函数声明!但是此声明函数一定要写到//DECLARE_MESSAGE_MAP()之前,因为这个函数要作为消息路由//中的函数处理,说白了,这个函数的调用是通过消息映射来调用的
    afx_msg LRESULT OnServerRecvMessage(WPARAM wParam,LPARAM lParam);
    DECLARE_MESSAGE_MAP()
     
    //接收函数定义!定义完了,上面也声明完了,但是怎么调用呢!
    LRESULT CServerDlg::OnServerRecvMessage(WPARAM wParam,LPARAM lParam)
    {
    switch ( LOWORD(lParam) )
    {
    case FD_READ:
    }
    return 0;
    }
     
    //这个就是消息路由的建立了,一定要写到两个宏之间,呵呵,前几天刚看完侯俊杰的MFC,所以觉得这个特别精髓,我记得我在写代码的时候我居然写到了另外一个类中,还好我明白原理,2分钟就找到错误了,如果要是以前的话,估计没有几天找不到。哈哈
    BEGIN_MESSAGE_MAP(XX子类,XX父类)
    ON_MESSAGE(UM_RECVMESSAGE,&XX子类:OnServerRecvMessage)
    END_MESSAGE_MAP()
     
    整理下思路,上面,注册了FD_READ消息。如果某个SOCKET变量收到了消息的话,就发送UM_RECVMESSAGE消息,并且我们关联了
    ON_MESSAGE(UM_RECVMESSAGE,&XX子类:OnServerRecvMessage)这个消息,所以发出UM_RECVMESSAGE消息之后,就调用OnServerRecvMessage这个函数了,这个函数就是接收消息,然后处理就可以了!
     
    其实就等于是把SOCKET和WINDOWS消息驱动结合起来了,但是用起来真的很方便,相比多线程节省了许多其他的步骤。
  • 相关阅读:
    一行代码轻松修改 Text Field 和 Text View 的光标颜色 — By 昉
    六种手势识别,你用了哪些?——董鑫
    Mac 屏幕录制Gif 制作 By-胡罗
    利用ICMP协议的PING命令获取客户端当前网络质量 by徐文棋
    iOS加载Gif图片的N种方式 By-H罗
    [手游项目3]-10-Go语言atomic原子操作
    [手游项目3]-9-Go语言sync.Map(在并发环境中使用的map)
    LRU原理和Redis实现
    Cleanup failed to process the following paths错误的解决
    [手游项目3]-8-排行榜redis实现
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/3995224.html
Copyright © 2011-2022 走看看