直到前两天才发现CAsyncSocket这个封装类(CSocket则是在CAsyncSocket基础上派生的一个同步阻塞Socket的封装类),找资料的时候关于它的详细资料应该是摘自《Windows网络编程》,更要哭的是这本书崇敬了好久一直没有找到~有一次特意跑到图书城去买~结果一看薄薄的一本(跟C++ Primer相比)要76大洋~~只好咽咽口水灰溜溜的回去了~~~这两天试着用了用~并且找了个网上的代码调试了一下~遇到相当多的问题,总结一下写出来~结论都是自我感觉的~因为调试的程序很少~又没有人告诉我~~也不好断定~有些还太清楚。所以事先声明::结论都是根据过程猜测的 哪里不对一定要告诉我 以免误人子弟哦
1。CAsyncSocket的派生类对象调用Create()函数的时候总是错误。
解决:用GetLastError()返回错误信息10093,查MSDN为WSANOTINITIALISED, 关于Create()函数中的解释为这个函数调用之前必须成功调用AfxSocketInit(),在MyApp::InitInstance()中调用解决。
结论:不知道是不是我个人的原因,我见到的其他人没有人提到要调用这个,我感觉CAsyncSocket既然封装了应该可以自己调用的。
2。调试《使用MFC快速实现网络编程CAsyncSocket》一文中的Echo程序,只能发送并返回一次。
解决:断点跟踪客户端程序,OnSend()和OnReceiver()函数均可正常调用。服务器程序转发对象接收第一次数据后OnReceive()函数就不再调用。发现只是在监听对象OnAccept()函数中调用了一次AsyncSelect(FD_READ),找不到更好的方法,只好在对话框程序中加入了OnTimer()函数,每100毫秒调用一次转发对象的AsyncSelect(FD_READ)<之前要判断对象是否已经创建并且连接>。
结论:本来一直以为一旦有数据到来系统能自动发送消息给CAsyncSocket类的对象窗口,而由此看来,还是要手工发送消息。也就是人工控制发送接受函数,只不过不会阻塞罢了。 哎~以前把它想的太“自动”了~~纠正观念~~~ [ 事实上本来想的是对的,这里的解决方法实际上是把WSAAsyncSocket异步模型降了一层,变为select模式了。这个问题的真正原因后面提到 ]``
3。自己写一程序,在Dlg中添加一个自定义类,自定义类中声明了个一个CAsyncSocket的派生类,创建正常,可是连接无论如何也无法激活OnReceive()函数,甚至直接调用AsyncSelect()也无法激活任何相应函数。
解决:使用网络监控软件来看Connect以后连接确实建立了,之后的send也返回了发送字节数,但是就是无法启动响应函数。跟踪后发现类中的回调函数docallback没有进入,自然也就没有了消息处理。而将CAsyncSocket的派生类在Dlg中声明,则所有函数工作正常。
结论:其间看了些资料,CAsyncSocket的i/o模型是基于窗口消息的,而他本身有自己的socketWnd窗口,但是这个窗口是在AfxSocketInit()函数调用时建立的。而我将CAsyncSocket用于了自定义的一个类,中间也没有传递窗口,自然就无法进行消息处理了~也就是说CAsyncSocket和CSocket都不能在无窗口模式下使用。而关于第二个问题的结论我也彻头彻尾的错了~~在能正常使用的情况下,一旦有数据到来系统确实能自动发送消息给CAsyncSocket类的对象窗口
而要在无窗口模式下使用异步模型,别人推荐使用WSAEventSelect模型,下一步要看他了~~~
=============================================
CAsyncSocket是非阻塞的,也就是它经常会返回值。当连接时,它返回错误,并不是真的有错。你可以GetLastError()然后判断是否为WSAEWOULDBLOCK,如果是这样,你可以忽略它,事实上已经建立了连接。另外,你用CSOCKET类就不会出现这种情况。因为他是阻塞的。
你应该派生CAsyncSocket类,或者CSocket类。从而你可以从基类中获得OnConnect,Onreceive,OnClose等许多事件,通过这些事件你才可能知道你的连接与数据传送是否正确。
一般Client端应该处理的事件是onconnect,onclose,onreceive(如果接收数据)。
Server端应处理onreceive,onclose,onreceive等。
注意,两端都要派生新类。从文档类中生成派生类的对象。