CSocket详解

来源:互联网 发布:excad激光软件 编辑:程序博客网 时间:2024/05/05 04:32

CSocket的用法
CSocket在CAsyncSocket的基础上,修改了Send、Recieve等成员函数,
帮你内置了一个用以轮询收发缓冲区的循环,变成了同步短连接模式。
短连接应用简单明了,CSocket经常不用派生就可以直接使用,但也
有些问题:
1、用作监听的时候
曾经看到有人自己创建线程,在线程中创建CSocket对象进行Listen、
Accept,若Accept成功则再起一个线程继续Listen、Accept。。。
可以说他完全不理解CSocket,实际上CSocket已经内置了多线程机制,
你只需要从CSocket派生,然后重载OnAccept:

//CListenSocket头文件class CListenSocket : public CSocket{public:CListenSocket(HWND hWnd=NULL);HWND m_hWnd; //事件处理窗口virtual void OnAccept(int nErrorCode);};//CListenSocket实现文件#include "ListenSocket.h"CListenSocket::CListenSocket(HWND hWnd){m_hWnd=hWnd;}void CListenSocket::OnAccept(int nErrorCode){SendMessage(m_hWnd,WM_SOCKET_MSG,SOCKET_CLNT_ACCEPT,0);CSocket::OnAccept(nErrorCode);}//主线程...m_pListenSocket=new CListenSocket(m_hWnd);m_pListenSocket->Create(...);m_pListenSocket->Listen();...LRESULT CXxxDlg::OnSocketMsg(WPARAM wParam, LPARAM lParam){UINT type=(UINT)wParam;switch(type){case SOCKET_CLNT_ACCEPT:{CSocket* pSocket=new CSocket;if(!m_pListenSocket->Accept(*pSocket)){delete pSocket;break;}...}...}}

2、用于多线程的时候
常看到人说CSocket在子线程中不能用,其实不然。实际情况是:
直接使用CSocket动态创建的对象,将其指针作为参数传递给子线程,
则子线程中进行收发等各种操作都没问题。但如果是使用CSocket的
派生类创建的对象,就要看你重载了哪些方法,假如你仅仅重载了
OnClose,则子线程中你也可以正常收发,但不能Close!
因为CSocket是用内部循环做到同步的,并不依赖各OnXxx,它不需
要与CSocketWnd交互。但当你派生并重载OnXxx后,它为了提供消息
机制就必须与CSocketWnd交互。当你调用AfxSocketInit时,你的主
线程会获得一个访问CSocketWnd的句柄,对CSocketWnd的访问是MFC
自动帮你完成的,是被隐藏的。而你自己创建的子线程并不自动具
备访问CSocketWnd的机制,所以子线程中需要访问CSocketWnd的操
作都会失败。
常看到的解决办法是不要给子线程传递CSocket对象指针,而是传递
SOCKET句柄,然后在子线程中创建CSocket临时对象并Attach传入的
句柄,用完后再Dettach并delete临时对象。俺没有这么干过,估计
是因为Attach方法含有获取CSocketWnd句柄的内置功能。
俺的解决方案还是使用自定义消息,比如俺不能在子线程中Close,
那么,俺可以给主线程发送一条消息,让主线程的消息处理函数来
完成Close,也很方便。

CSocket的运作流程
CSocket一般配合多线程使用,只要你想收发数据,你就可以创建一
个CSocket对象,并创建一个子线程来进行收发。所以被阻塞的只是
子线程,而主线程总是可以随时创建子线程去帮它干活。
由于可能同时有很多个CSocket对象在工作,所以你一般还要创建一
个列表来储存这些CSocket对象的标识,这样你可能通过在列表中检
索标识来区分各个CSocket对象,当然,由于内存地址的唯一性,对
象指针本身就可以作为标识。
相对CAsyncSocket而言,CSocket的运作流程更直观也更简单,至于
CSocketFile、CArchive之类的,似乎也不需要多说什么,就这样结
束吧。

0 0
原创粉丝点击