最近想起CAsyncSocket这个类,记得很早以前用过,现在却想不起来怎么用了,翻了翻以前的代码又看了看msdn感觉这个类做简单的异步socket太简单了,几行代码就可以搞定,在此先做个总结。
不管是客户端和服务端都要从CAsyncSocket这个类派生一个类来重载一系列Socket消息事件函数比如 CAsyncSocket::OnAccept CAsyncSocket::OnReceive 等
1.服务端
1.1首先派生一个类用来监听
class CListenSocket : public CAsyncSocket { public: public: CListenSocket(); virtual ~CListenSocket(); void SetListBox(CListBox * ListBox) {m_ListBox = ListBox;} //这个ListBox是主窗口里面的一个客户端列表用来显示有几个客户端 void SetListBoxMsg(CListBox * ListBox) {m_ListBoxMsg = ListBox;} //这个ListBox是接收客户端消息的 public: virtual void OnAccept(int nErrorCode); virtual void OnClose(int nErrorCode); CClientSocket * GetClientByIndex(int nIndex) //返回一个已经连接的客户端用来给指定客户端发消息 { return m_ClientSocketList.GetAt(m_ClientSocketList.FindIndex(nIndex)); } private: CList<CClientSocket * > m_ClientSocketList; //这里要维护一个已经连接的客户端列表,这样服务器可以指定向哪个服务器发消息 CListBox * m_ListBox; CListBox * m_ListBoxMsg; };
要响应监视类的Accept事件
void CListenSocket::OnAccept(int nErrorCode) { // TODO: 在此添加专用代码和/或调用基类 if (nErrorCode == 0)//如果成功 { CClientSocket* pNewClientSocket = new CClientSocket(); //保存一个已经连接的客户端 BOOL bAccept=Accept(*pNewClientSocket); if (bAccept) { m_ClientSocketList.AddTail(pNewClientSocket); pNewClientSocket->SetListBox(m_ListBoxMsg); CString SocketName; UINT len = 100; pNewClientSocket->GetSockName(SocketName,len); m_ListBox->AddString(SocketName); //客户端列表里显示这个已经连接的客户端ip } else { DWORD dwErr = GetLastError(); CString strErr; strErr.Format(_T("accept 错误码=%d"),dwErr); delete pNewClientSocket; AfxMessageBox(strErr); } } CAsyncSocket::OnAccept(nErrorCode); }
已经连接客户端对象也是从CAsyncSocket派生来的、
class CClientSocket : public CAsyncSocket { public: CClientSocket(); virtual ~CClientSocket(); virtual void OnReceive(int nErrorCode); virtual void OnClose(int nErrorCode); VOID SetListBox(CListBox * ListBox) {m_ListBox = ListBox;} CListBox * m_ListBox; private: };
当服务端收到消息时要响应事件OnReceive
void CClientSocket::OnReceive(int nErrorCode) { // TODO: 在此添加专用代码和/或调用基类 if (nErrorCode == 0) { char szBuf[1024] = {0}; INT nReceiveCounts = Receive((VOID*)szBuf,1024); if(m_ListBox != NULL) m_ListBox->AddString(szBuf); } CAsyncSocket::OnReceive(nErrorCode); }
1.2 监听
void CMfcSocketDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 if(m_ListenSocket != NULL) return ; BOOL bInit = AfxSocketInit(); if(!bInit) { AfxMessageBox(_T("socket 初始化失败 ")); return ; } m_ListenSocket = new CListenSocket(); BOOL bCreate = m_ListenSocket->Create(10101); if(!bCreate) { AfxMessageBox(_T("创建失败")); delete m_ListenSocket; m_ListenSocket = NULL; } BOOL bListen = m_ListenSocket->Listen(); if(!bListen) { AfxMessageBox(_T("监听失败!")); delete m_ListenSocket; m_ListenSocket = NULL; } m_ListenSocket->SetListBox(&m_ListBoxClientList); //客户端列表 m_ListenSocket->SetListBoxMsg(&m_ListBoxRecMsg); //已经接收的消息 }
2.客户端
2.1 派生一个类用来作为客户端socket
#include "afxsock.h" class CClientSocket : public CAsyncSocket { public: CClientSocket(void); virtual ~CClientSocket(void); virtual void OnReceive(int nErrorCode); virtual void OnClose(int nErrorCode); virtual void OnConnect(int nErrorCode ); void SetListBox(CListBox * ListBox) {m_ListBox = ListBox;} CListBox * m_ListBox; };
想接收消息就要响应接收消息的事件
void CClientSocket::OnReceive(int nErrorCode) { if(nErrorCode == 0) { CString szBuf; INT nReceiveCounts = Receive((VOID*)szBuf.GetBuffer(1000),1000); m_ListBox->AddString(szBuf); } }
2.2 客户端对象的创建和连接
void CMfcSocketClientDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 UpdateData(TRUE); BOOL bInit = AfxSocketInit(); if(!bInit) { AfxMessageBox(_T("socket 初始化失败 ")); return ; } if(m_ClientSocket == NULL) { m_ClientSocket = new CClientSocket; m_ClientSocket->Create(); } else { m_ClientSocket->Close(); } m_ClientSocket->Connect(m_Ip,m_Port); m_ClientSocket->SetListBox(&m_ListBox); }
上个图片上源码供新手学习