002篇是采用传统方式创建,不适应动态的网络环境,服务器为客户端保留着断开连接时的套接字,不够灵活。而采用指针机制不仅可以更加灵活性,而且能使代码更集中,更具有条理性。将其转变成指针机制。功能及运行保持一致。(前文链接:https://www.cnblogs.com/maxonzou/articles/10573105.html)
1、通信套接字实例改动。
1)客户端:在ClientSocket类中新增函数pGetDlg用户快速获取主窗口指针,并声明一个Dlg类的指针用于绑定,在CXXXDlg.h中声明对象m_ClientSocket改成指针型。
2)服务端:并新增一个Dlg类的指针用于实现函数快速获取指针。在CXXXDlg.h中声明创对象m_ListenSocket/m_ServerSocket改成指针型。
Tips:此时应将Socket.h中的Dlg.h头文件改成类声明class CXXXDlg,否则会导致头文件循环引用出错。
1 // XXXSocke.h中 2 3 class CXXXDlg; //类声明,创建指针对象 4 class XXXSocket : public CAsyncSocket 5 { 6 public: 7 CXXXXDlg *m_dlg; 8 void pGetDlg(CXXXXDlg*dlg); 9 ...... 10 }
11 //在CXXXXSocket中实现函数,其实pGetFlg就是将Ccase003Dlg* plist=(Ccase003Dlg*)(AfxGetApp()->m_pMainWnd)封装成函数。
12 void CxxxxSocket::pGetDlg(CxxxxDlg* dlg)
13 {
14 m_dlg=dlg;
15 }
2、将通信事件集中到Dlg类中,并对Socket对象初始化。
因指定为指针型,在Dlg.cpp的初始化InitInstance函数中中进行指针初始化(=NULL),在Socket对象中我们指定了窗口类指针,便是用于回调在Dlg类中实现函数。重写退出函数(释放所有对象指针)。
1 class CXXXXDlg : public CDialog 2 { 3 public: 4 CXXXXSocket * m_xxxxsocket; //客户端一个,服务器端两个,一个用于监听,一个用于服务 5 void OnReceive(); 6 void OnClose(); 7 void OnConnect(); 8 void Reset(); //用于释放套接字对象 9 ...... 10 } 11 //在Dlg.cpp中实现Reset函数,即删除套接字对象,并将指针赋空 12 void CXXXDlg::Reset() 13 { 14 if(m_xxxxSocket!=NULL) 15 { 16 Delete m_xxxxSocket; 17 m_xxxxSocket=NULL; 18 } 19 } 20 21 void CXXXXDlg::OnBnClickedCancel() //采用指针机制,在退出时需确保指针释放 22 { 23 // TODO: 在此添加控件通知处理程序代码 24 Reset(); 25 OnCancel(); 26 }
此时精简Socket类中的函数,使用m_dlg->OnClose()方式,将对应函数中的操作语句(除了判定语句外)全部转移到Dlg类中相应函数体,这样对于控件变量就无需再增加指针定向了。注意OnReceive/OnAccept中使用的Receive/Accept是Socket的成员函数,故转移后应增加“m_clientsocket->" 或"m_serversocket->”补充。
3、实例化套接字对象,并更新Dlg.cpp中的函数
1)客户端:在连接时应实例化一个Socket对象,并绑定指针到主窗口,将c_xxxxSocket的"."操作全部切换成"->"操作;
2)服务器端:在开始监听时创建监听对象,在Accept中创建服务对象,同时绑定指针到主窗口。将c_xxxxSocket的"."操作全部切换成"->"操作。
1 { 2 m_XXXXsocket = new CXXXXSocket; 3 m_XXXXsocket->pGetDlg(this); 4 }
4、运行调试。
客户端在运行后会有提示在CXXXXSocket.cpp类中存在未声明对象,此时发现原来是之前为了避免连接失败不清空套接字增加的语句导致“plist->m_clientsocket->Close();”删除。
客户端:在所有执行m_xxxxSocket->Close()语句后追加Reset()彻底释放套接字对象。
服务器端:在所有执行m_xxxxSocket->Close()语句后释放套接字对象。因为有两个Socket对象,所以要分别释放,不能直接调用Reset。
1 if(m_XXXXsocket!=NULL) 2 { 3 delete m_XXXXsocket; 4 m_XXXXsocket=NULL; 5 }
5、小结:会者不难,先了解原理,然后再码代码。
1)指针机制的使用注意及时释放指针,尽量将代码集中在主程序文件中;
2)异步通信:服务器端打开监听(Listen),触发Accept接收请求,客户端发出连接,触发connect发送请求,至此可实现连接。发送信息使用Send,有信息触发相应端Receive接收显示信息。