网络课设总结(四)——利用CAsyncSocket进行异步通信

一、先提供成品,即可以执行的代码

     CAsyncSocket封装了Windows Sockets API,用于表示网络通信的Socket端点

1、CServerSocket.h

#if !defined(AFX_SERVERSOCKET_H__023D856C_FEA7_4A0D_B8E3_180AFFCC462C__INCLUDED_) #define AFX_SERVERSOCKET_H__023D856C_FEA7_4A0D_B8E3_180AFFCC462C__INCLUDED_ //#include "ClientSocket.h" #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // ServerSocket.h : header file // / // CServerSocket command target class CServerSocket : public CAsyncSocket { // Attributes public: // Operations public: CServerSocket(); virtual ~CServerSocket(); // Overrides public: void DeleteRemoteSocket(CClientSocket* pSock); //删除客户端连接 POSITION GetRemoteSocketPos(CClientSocket* pSock); //获取制定客户端在链表中的位置 public: CPtrList m_clientList; //客户端SOCKET链表 HWND m_hdlgWnd; //接收消息的窗口句柄对象 UINT port; //监听端口 int bListened; //标志是否处于监听状态,1为监听状态,0为非监听状态 // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CServerSocket) public: virtual void OnAccept(int nErrorCode); virtual void OnClose(int nErrorCode); //}}AFX_VIRTUAL // Generated message map functions //{{AFX_MSG(CServerSocket) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG // Implementation protected: }; / //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_SERVERSOCKET_H__023D856C_FEA7_4A0D_B8E3_180AFFCC462C__INCLUDED_)

2、够造函数和析构函数

CServerSocket::CServerSocket() { // m_hdlgWnd=hWnd; port=0; bListened=1; } CServerSocket::~CServerSocket() { while (!m_clientList.IsEmpty()) { CClientSocket* client = (CClientSocket*) m_clientList.RemoveHead();//获取首个客户端对象 client->Close();//关闭客户端 delete client;//删除客户端 } m_clientList.RemoveAll();//移除所有客户端 if (m_hSocket != INVALID_SOCKET)//如果窗口句柄有效,关闭 { Close(); } }

3、CServerSocket.cpp涉及网络通信的函数分析

(1)、OnAccept函数

在此,要对错误参数进行处理,完善出错机制;如果在堆上申请内存,要在该函数的每一个出口处用delete将其释放,否则会照成内存泄漏;调试技巧:如果感觉某个地方有问题,设置一个变量,获取想要求证的值,比方说,在此我想验证自己新建的客户端Socket是否已经存放在m_ClientList里面,就用如下一句话CClientSocket* p=(CClientSocket*)m_clientList.GetTail();然后,单步跟踪到此处,查看p的值是否为pSocket的值即可。如下图:

代码如下:

 

/************************************************************************/ /*函数名称:OnAccept /*功能描述:通知监听套接字,告诉它可以通过调用Accept函数来响应连接请求 /*函数参数:nErrorCode——标志发生在套接字上的最近错误,0表示该函数成功执行; WSAENETDOWN表示该函数执行失败。 /*返回结果:void /************************************************************************/ void CServerSocket::OnAccept(int nErrorCode) { //在每一个new操作后,都要记得在该段程序的出口处将申请的内存释放 char* pLog = new char[200];//定义消息日志 if (nErrorCode)//根据参数进行错误处理 { if (nErrorCode == WSAENETDOWN) { sprintf(pLog, "网络故障!"); } else { sprintf(pLog, "FD_ACCEPT未知错误"); } delete pLog;//及时释放内存 return; } else { sockaddr address;//定义地址变量 CString IPaddr; UINT port; int address_len; address_len = sizeof(address); //疑问:此处,如果不把CSocketClient的构造函数里的代码全部注释的话,就会产生错误,为什么? CClientSocket *pSocket= new CClientSocket();//在堆上创建CSocketClient对象 pSocket->m_dlg=this->m_hdlgWnd; if (Accept(*pSocket, &address, &address_len)) { pSocket->AsyncSelect(FD_WRITE | FD_READ | FD_CLOSE);//设置数据发送套接字的读、写、关闭事件 pSocket->GetPeerName(IPaddr, port);//获取IP地址和端口号 pSocket->m_ipOppsite = IPaddr; pSocket->m_portOppsite = port; m_clientList.AddTail((void*)pSocket); SendMessage(m_hdlgWnd, WM_SOCKET_CONNECT,0,0); // CClientSocket* p=(CClientSocket*)m_clientList.GetTail();//调试技巧!!! } else { int Error = GetLastError(); if (Error == WSAECONNREFUSED) { sprintf(pLog, "拒绝连接"); } else { wsprintf(pLog, "WSAAccept失败,错误代码:%d", Error); } delete pSocket; delete pLog; return; } } CAsyncSocket::OnAccept(nErrorCode); }

(2)、OnClose函数

/************************************************************************/ /*函数名称:OnClose /*函数功能:通知套接字与它相连的Socket已经被进程关闭 /*函数参数:nErrorCode——标志发生在套接字上的最近错误,0表示该函数成功执行; WSAENETDOWN表示该函数执行失败。 /*返回结果:void /************************************************************************/ void CServerSocket::OnClose(int nErrorCode) { while (!m_clientList.IsEmpty()) { CClientSocket* client = (CClientSocket*) m_clientList.RemoveHead();//获取首个客户端对象 client->Close();//关闭客户端 delete client;//删除客户端 } m_clientList.RemoveAll();//移除所有客户端 if (m_hSocket != INVALID_SOCKET)//如果窗口句柄有效,关闭 { Close(); } CAsyncSocket::OnClose(nErrorCode); }

 

你可能感兴趣的:(VC++/VC++.NET)