更新时间:2024-02-27 18:55
CSocket是MFC在CAsyncSocket基础上派生的一个同步阻塞Socket的封装类,它的定义包含在afxsock.h中。它是如何又把CAsyncSocket变成同步的,而且还能响应同样的Socket事件呢?
PumpMessage会遇到下面几种情况:
1 提取出了(从消息队列中移出来Remove),用户正在使用的一个Socket发送的WM_SOCKET_NOTIFY消息和对应的 FD_XXX事件,返回True.
2 提取出了(从消息队列中移出来Remove),用户正在使用的一个Socket发送的WM_SOCKET_NOTIFY消息和对应的 FD_Close事件,返回True.
3 提取出了(从消息队列中移出来Remove),PumpMessage(..)设定的定时器的WM_TIMER消息,TimeOut事件为 CSocket的一个成员变量,m_nTimeOut=2000ms,返回True
4 用户调用了CancelBlockingCall() 设置错误代码为WSAEINTR(被中断了),返回False
5 用户一直没有取到用户正在使用的一个Socket发送的WM_SOCKET_NOTIFY消息和对应的FD_XXX事件,但是取到了同一个线程中的其他Socket的WM_SOCKET_NOTIFY消息及其对应的消息,则将这些消息,加入到一个辅助性的队列中去,以后处理.
6 没有取到任何WM_SOCKET_NOTIFY消息,则开始查看(不是取出来,而是查看)本线程的消息队列中是否有其它消息,如果有的话,调用虚函数OnMessagePending(),来处理这些消息(OnMessagePending()用户可以自定义。在阻塞时,用户想要处理的消息),如果没有,则调用WaitMessage()开始等待消息的到来.
代码说明如下:
A 先看Connect,因为Connect的阻塞的实现和Accept,Receive,ReceiveFrom,Send,SendTo都有点不同.
也许你们会奇怪为何是ConnectHelper(...),而不是Connect(...).其实ConnectHelper(...)才是Connect(..)
真正调用的东西,如下:
CSocket模式与socket API模式的最大区别在于它实现了:
1、将socket事件消息化
2、用消息阻塞方式实现同步
3、用序列化方式读写数据以防止死锁,简化读取数据模型(流数据)。
多线程编程时,由于CSocket不能跨线程使用,所以,新建工作线程中会有一个CSocket对象,而该对象会重新与已知SOCKET句柄重新Attach,实现在新的线程中以CSocket对象的方式编程。
然后使用消息通信的方式,实现在新建线程中读写数据。
通过消息、线程事件等同步机制 实现UI线程与CSocket对象所在工作线程的通信,并不会影响UI的响应。
在BOOL CSocket::PumpMessages(UINT uStopFlag)中
看OnMessagePending:
但上面针对的都是当前线程的WM_PAIT消息,而不是跨线程的,而多线程模式下的SOCKET都是放在工作线程中执行的!