CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  基础类

WSAAsyncSelect 函数参数问题

楼主mjs2000(宁静致远)2002-03-04 14:42:38 在 VC/MFC / 基础类 提问

自己写了一个类继承了CCmdTarget,其中包含下面得函数  
  int   WSAAsyncSelect   (  
      SOCKET   s,                        
      HWND   hWnd,                      
      unsigned   int   wMsg,      
      long   lEvent                    
  );  
  hWnd是否可以为NULL,  
  如果可以的话,是否是类本身接受这个消息,希望大家指导 问题点数:50、回复次数:10Top

1 楼mjs2000(宁静致远)回复于 2002-03-04 14:55:46 得分 0

大家帮忙了Top

2 楼silverwgy(yiyi)回复于 2002-03-04 14:55:55 得分 10

不可以,hWnd用NULL会接收不到任何消息的Top

3 楼morningsing(奈何)回复于 2002-03-04 15:06:33 得分 10

必需要指定一个存在的窗口,不然的话,谁来接受消息呢?  
  换句话讲,你在哪里响应socket消息呢?Top

4 楼mjs2000(宁静致远)回复于 2002-03-04 15:07:11 得分 0

也就是说我要写几个虚函数,来让hWnd来继承了???  
   
  如果我的hWnd只是一个CWnd类,并非窗口可以吗??Top

5 楼mjs2000(宁静致远)回复于 2002-03-04 15:10:53 得分 0

我看了CAsyncSocket没有设定hwnd怎么还可以接受消息呢?Top

6 楼mjs2000(宁静致远)回复于 2002-03-04 15:20:20 得分 0

class   CSocketWnd   :   public   CWnd  
  {  
  //   Construction  
  public:  
  CSocketWnd();  
   
  protected:  
  //{{AFX_MSG(CSocketWnd)  
  LRESULT   OnSocketNotify(WPARAM   wParam,   LPARAM   lParam);  
  LRESULT   OnSocketDead(WPARAM   wParam,   LPARAM   lParam);  
  //}}AFX_MSG  
  DECLARE_MESSAGE_MAP()  
  };  
   
  是不是这个类的缘故啊?里面怎么写的呢?怎么可以接受消息了呢?》Top

7 楼Reflect(无知者无畏)回复于 2002-03-04 15:25:47 得分 0

CAsyncSocket其实也创建了一个窗口,只是将它隐藏了  
  Top

8 楼mjs2000(宁静致远)回复于 2002-03-04 15:27:45 得分 0

to     Reflect(长春藤的心情)   请具体解释Top

9 楼mjs2000(宁静致远)回复于 2002-03-04 15:28:21 得分 0

to     Reflect(长春藤的心情)   请具体解释Top

10 楼mjs2000(宁静致远)回复于 2002-03-04 15:46:01 得分 0

大家帮忙啊Top

11 楼Reflect(无知者无畏)回复于 2002-03-04 15:47:31 得分 30

CAsyncSocket在AttachHandle中有以下代码  
  CSocketWnd*   pWnd   =   new   CSocketWnd;  
  pWnd->m_hWnd   =   NULL;  
  if   (!pWnd->CreateEx(0,   AfxRegisterWndClass(0),  
  _T("Socket   Notification   Sink"),  
  WS_OVERLAPPED,   0,   0,   0,   0,   NULL,   NULL))  
  {  
  TRACE0("Warning:   unable   to   create   socket   notify   window!\n");  
  AfxThrowResourceException();  
  }  
  从此你可以看到,其实是又窗体的  
  以上代码在sockcore.cpp中。Top

12 楼yobyalp(外外子)回复于 2002-05-16 10:42:13 得分 0

这个问题其实很简单,请参见:  
  /////////  
  WSAAsyncSelect()  
  简述:  
  通知套接口有请求事件发生.  
   
  #include   <winsock.h>  
   
  int   PASCAL   FAR   WSAAsyncSelect   (   SOCKET   s,   HWND   hWnd,  
  unsigned   int   wMsg,     long   lEvent   );  
   
  s       标识一个需要事件通知的套接口的描述符.  
  hWnd         标识一个在网络事件发生时需要接收消息的窗口句柄.  
  wMsg         在网络事件发生时要接收的消息.  
  lEvent     位屏蔽码,用于指明应用程序感兴趣的网络事件集合.  
   
  注释:  
  本函数用来请求Windows   Sockets   DLL为窗口句柄发一条消息-无论它何时检测到由lEvent参数指明的网络事件.要发送的消息由wMsg参数标明.被通知的套接口由s标识.  
  本函数自动将套接口设置为非阻塞模式.  
  lEvent参数由下表中列出的值组成.  
  值             意义  
  FD_READ   欲接收读准备好的通知.  
  FD_WRITE         欲接收写准备好的通知.  
  FD_OOB     欲接收带边数据到达的通知.  
  FD_ACCEPT       欲接收将要连接的通知.  
  FD_CONNECT     欲接收已连接好的通知.  
  FD_CLOSE         欲接收套接口关闭的通知.  
   
  启动一个WSAAsyncSelect()将使为同一个套接口启动的所有先前的WSAAsyncSelect()作废.   例如,要接收读写通知,应用程序必须同时用FD_READ和FD_WRITE调用WSAAsyncSelect(),如下:  
  rc   =   WSAAsyncSelect(s,   hWnd,   wMsg,   FD_READ|FD_WRITE);  
  对不同的事件区分不同的消息是不可能的.下面的代码将不会工作;第二个调用将会使第一次调用的作用失效,只有FD_WRITE会通过wMsg2消息通知到.  
  rc   =   WSAAsyncSelect(s,   hWnd,   wMsg1,   FD_READ);  
  rc   =   WSAAsyncSelect(s,   hWnd,   wMsg2,   FD_WRITE);  
   
  如果要取消所有的通知,也就是指出Windows   Sockets的实现不再在套接口上发送任何和网络事件相关的消息,则lEvent应置为0.  
  rc   =   WSAAsyncSelect(s,   hWnd,   0,   0);  
   
  尽管在本例中,WSAAsyncSelect()立即使传给该套接口的事件消息无效,   仍有可能有消息等在应用程序的消息队列中.应用程序因此也必须仍准备好接收网络消息-即使消息作废.用closesocket()关闭一个套接口也同样使WSAAsyncSelect()发送的消息作废,但在closesocke()之前队列中的消息仍然起作用.  
  由于一个已调用accept()的套接口和用来接收它的侦听套接口有同样的属性,   任何为侦听套接口设置的的WSAAsyncSelect()事件也同样对已接收的套接口起作用.例如,   如果一个侦听的套接口有WSAAsyncSelect()事件FD_ACCEPT,FD_READ,FD_WRITE,   则任何在那个侦听的套接口上接收的套接口将也有FD_ACCEPT,FD_READ,FD_WRITE事件,以及同样的wMsg的值.若需要不同的wMsg及事件,应用程序应调用WSAAsyncSelect(),将已接收的套接口和想要发送的新消息作为参数传递.  
  当某一套接口s上发生了一个已命名的网络事件,应用程序窗口hWnd会接收到消息wMsg.wParam参数标识了网络事件发生的套接口.lParam的低字指明了发生的网络事件.lParam的高字则含有一个错误代码.该错误代码可以是winsock.h中定义的任何错误.  
  错误代码和事件可以通过WSAGETSELECTERRORH和WSAGETSELECTEVENT宏从lParam中取出.定义如下:  
      #define   WSAGETSELECTERROR(lParam)                         HIWORD(lParam)  
      #define   WSAGETSELECTEVENT(lParam)                         LOWORD(lParam)  
  注意:在accept()调用和为改变事件或wMsg的WSAAsyncSelect()调用中有一个计时窗口.应用程序如果需要给侦听的和调用过accept()的套接口以不同的wMsg,它就应该在侦听的套接口上请求FD_ACCEPT事件,然后在accept()调用后设置相应的事件.由于FD_ACCEPT从不发送给已连接的套接口,而FD_READ,FD_WRITE,FD_OOB及FD_CLOSE也从不发送给侦听套接口,所以不会产生困难.  
  使用以上的宏将最大限度的提高应用程序的可移植性.  
  返回的可能网络事件如下:  
  值             意义  
  FD_READ   套接口s准备读  
  FD_WRITE         套接口s准备写  
  FD_OOB     带外数据准备好在套接口s上读.  
  FD_ACCEPT       套接口s准备接收新的将要到来的连接.  
  FD_CONNECT     套接口s上的连接完成.  
  FD_CLOSE         由套接口s标识的连接已关闭.  
   
  返回值:  
  0                       若应用程序感兴趣的网络事件的声明成功.  
  SOCKET_ERROR         否则.可通过调用WSAGetLastError()返回特定的错误代码.  
   
  评价:  
  尽管WSAAsyncSelect()可以以多个事件的组合来调用,应用程序窗口还是会为每个网络事件接收一条消息.  
  如同select()函数,WSAAsyncSelect()会被频繁地调用来决定,何时一次数据转移操作(send()或recv())可以启动,并且可以立刻成功.尽管如此,健壮的应用程序必须做好这样的准备,   即它可能接收到消息及启动了一个会立即返回WSAEWOULDBLOCK的Windows   Sockets   API调用.例如,下列的事件序列是可能的:  
  (i)   数据到达套接口s;Windows   Sockets传递WSAAsyncSelect消息.  
  (ii)         应用程序处理其它一些消息.  
  (iii)       在处理过程中,应用程序启动了ioctlsocket(s,FIONREAD...)并且注意到有数据准备好读.  
  (iv)         应用程序启动recv(s,...)来读数据.  
  (v)   应用程序循环处理下一条消息,最终到达WSAAsyncSelect消息,表示数据已准备好读.  
  (vi)         应用程序启动recv(s,...),但失败并有错误WSAEWOULDBLOCK.  
  其它的事件序列也是可能的.  
  Windows   Sockets   DLL不会不断地为某一特定的网络事件向一个应用程序发送消息.   如果已成功地向应用程序窗口发送了一特定事件的通知,对该应用程序窗口将不再为该网络事件发消息,直到应用程序调用函数隐含地重新通知该网络事件.  
  事件                 重新通知函数  
  FD_READ   recv()或recvfrom()  
  FD_WRITE         send()或sendto()  
  FD_OOB     recv()  
  FD_ACCEPT       accept()  
  FD_CONNECT     无  
  FD_CLOSE         无  
  任何对重新通知函数的调用,即使失败,也会达到为相关事件发重新通知消息的效果.  
  对FD_READ,FD_OOB和FD_ACCEPT事件,消息传递是"水平触发"(level-triggered)的.这意味着,若调用了重新通知函数并且相关的事件对该调用仍有效,WSAAsyncSelect()消息就将传给应用程序.这为应用程序提供了事件驱动以及不必考虑在任一时刻到达的数据量的能力.考虑下列序列:  
  (i)   Windows   Sockets   DLL在套接口s上接收100字节的数据并传递一个FD_READ消息.  
  (ii)         应用程序启动recv(s,buffptr,50,0)接收50字节.  
  (iii)       由于仍有数据未读,Windows   Sockets   DLL发送另一个FD_READ消息.  
   
  根据以上语义,应用程序不必在收到FD_READ消息时读进所有可读的数据-对应于每一FD_READ消息进行一次recv()调用是恰当的.如果应用程序为一个FD_READ消息而启动了多个recv()调用,它将接收到多个FD_READ消息.这样的应用程序可能希望在开始recv()调用(   通过不为FD_READ事件置位的WSAAsyncSelect()函数调用)之前关闭FD_READ消息.  
  如果在应用程序初次调用WSAAsyncSelect()或当调用了重新通知函数时,有一个事件为真,   则会发送一个相应的消息.例如,若应用程序调用listen(),就会试图进行连接,然后应用程序调用WSAAsyncSelect()声明它需要为套接口接收FD_ACCEPT消息,Windows   Sockets的实现就会立即传递一个FD_ACCEPT消息.  
  FD_WRITE事件处理起来稍有不同.FD_WRITE消息是在套接口第一次用connect()连接或由accept()接受,并且在send()或sendto()以WSAWOULDBLOCK错误失败后缓冲区空闲时发送的.因此,应用程序可以假设发送可能在第一次FD_WRITE消息时开始,并持续到一次返回WSAEWOULDBLOCK的发送.   在这样的失败后,应用程序将被通知,FD_WRITE消息的发送又将可能.  
  FD_OOB事件只用在当套接口配置成独立接收带外数据时.如果一个套接口被配置成接收感兴趣的带外数据状态,带外数据将和普通数据等同视之,并且应用程序应该注册它感兴趣的方面,然后将接收FD_READ事件,而不是FD_OOB事件.应用程序可以设置或监控带外数据处理的方法(通过使用setsockopt()或getsockopt()函数,及SO_OOBINLINE选项).  
  在FD_CLOSE消息中的错误代码指出套接口的关闭是正常的还是异常的.如果错误代码是0,则关闭是正常的;若错误代码是WSAECONNRESET,则套接口的虚套接口将被重置.这些只对SOCK_STREAM类型的套接口起作用.  
  FD_CLOSE消息在相应套接口的虚电路关闭指令接收到时发送.在TCP术语中,这意味着FD_CLOSE在连接进入了FIN   WAIT或CLOSE   WAIT状态时发送.这是远端对发送方进行了shutdown()调用或closesocket()调用的结果.  
  请注意你的应用程序将只会收到FD_CLOSE消息来指出虚电路的关闭.它不会收到FD_READ消息来表示该状况.  
   
  错误代码:  
  WSANOTINITIALISED               在使用本API前必须进行一次成功的WSAStartup()调用.  
  WSAENETDOWN           WINDOWS   SOCKETS实现已检测到网络子系统故障.      
  WSAEINVAL                       指出指定的参数之一是非法的.  
  WSAEINPROGRESS             一个阻塞的Windows   Sockets操作正在进行.  
  附加的错误代码可能在应用程序窗口接收到消息时被置.这些代码可以用WSAGETSELECTERROR宏从lParam中取出.对应于每个网络事件的可能错误代码为:  
  事件:FD_CONNECT  
  WSAEADDRINUSE               给定的地址已被使用.  
  WSAEADDRNOTAVAIL                 指定的地址在本地机器不能使用.  
  WSAEAFNOSUPPORT           指定族的地址不能和本套接口同时使用.  
  WSAECONNREFUSED           连接的尝试被拒绝.  
  WSAEDESTADDRREQ           需要一个目的地址.  
  WSAEFAULT                       namelen参数不正确.  
  WSAEINVAL                       套接口已经约束到一个地址.  
  WSAEISCONN                     套接口已经连接.  
  WSAEMFILE                       没有可用的文件描述符.  
  WSAENETUNREACH             此时网络不能从该主机访问.  
  WSAENOBUFS                     无可用的缓冲区空间.套接口不能连接.  
  WSAENOTCONN           套接口没有连接.  
  WSAENOTSOCK           该描述符是文件,不是套接口.  
  WSAETIMEDOUT                 试图连接超时,未建立连接.  
  事件:FD_CLOSE  
  WSAENETDOWN           WINDOWS   SOCKETS实现已检测到网络子系统故障.      
  WSAECONNRESET               连接由远端重建.  
  WSAECONNABORTED           由于超时或其它失败放弃连接.  
  事件:FD_READ  
  事件:FD_WRITE  
  事件:FD_OOB  
  事件:FD_ACCEPT  
  Top

相关问题

  • 关于WSAAsyncSelect回调函数的参数问题
  • biosdisk()函数参数
  • 函数和参数
  • 传递函数做参数
  • 函数得参数问题
  • 函数参数的疑惑
  • C++ 函数参数问题!
  • main函数参数问题
  • 函数做参数问题
  • 函数参数的问题

关键词

  • 函数
  • 接口
  • 消息
  • sockets
  • 网络
  • null
  • wsaasyncselect
  • 接收
  • 通知
  • csocketwnd

得分解答快速导航

  • 帖主:mjs2000
  • silverwgy
  • morningsing
  • Reflect

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo