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

      上一篇文章,我给大家提供了服务器监听套接字的基本代码,这一篇文章,让我们一起来看看客户端的代码!!!

      由于,我要完成的功能是在一个对话框里轮流显示和管理多个服务器和多个客户端,因此在建立套接字类的时候费了一番脑筋;在此我将整个过程描述出来,也许对面向对象的程序设计有一点启示。

初步方案:

服务器端的职责是监听和数据通信,客户端的功能是数据通信;好的,我直接就这么考虑了,我需要一个监听套接字类,一个数据通信套接字类,然后在以数据通信套接字和监听套接字为成员变量构成服务器端套接字类;客户端类直接用数据通信套接字。首先,这个想法在思维上很顺利,看起来顺理成章,在实现的时候却发现,服务器端有这样的问题:一个服务器端套接字可以对应多个客户端;好的,那么在处理服务器端的管理问题的时候,我发现,服务器端的本质是什么?监听,对就是监听。除了监听,没有别的。

改进方案:

服务器端只负责监听,一个监听套接字类足够;如果收到客户端的连接请求,则在本机创建一个“客户端”,与那个客户端通信!!!至少到目前看来,这个方案还是比较优化的。

 

        总结:在这过程中,我感觉面向对象的思想博大精深,我的领会还很肤浅。在改进的过程中,感觉对自己最大的一个帮助就是,明确系统中每个对象的职责,从本质上去理解问题。

1、lientSocket.h:

class CClientSocket : public CAsyncSocket { // Attributes public: // Operations public: CClientSocket(); virtual ~CClientSocket(); // Overrides public: int m_nLength;//定义数据长度 char* m_szReceBuf;//定义接收缓存区 char* m_szSendBuf;//定义发送缓冲区 bool m_bConnect;//定义连接状态标志 //保存对方IP地址,如果该类的对象是由监听端口管理的,那么它保存的就是客户端的IP地址; //如果该类的对象是客户端对象,那么它就保存服务器的IP地址。 CString m_ipOppsite; int m_portOppsite;//用法如上 HWND m_dlg; // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CClientSocket) public: virtual void OnReceive(int nErrorCode); virtual void OnConnect(int nErrorCode); //}}AFX_VIRTUAL // Generated message map functions //{{AFX_MSG(CClientSocket) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG // Implementation protected: };

2、OnConnect函数

/************************************************************************/ /*函数名称:OnConnect /*功能描述:无论成功或出错,通知要求进行连接的Socket,其连接企图已经完成 /*函数参数:nErrorCode——标志发生在套接字上的最近错误,具体含义详见MSDN /*返回结果:void /************************************************************************/ void CClientSocket::OnConnect(int nErrorCode) { char* pLog = new char[MASSAGENUM];//定义消息变量 if (0 == nErrorCode) { sprintf(pLog, "连接服务器成功");//复制消息提示信息到消息变量中 m_bConnect = true; } else { switch (nErrorCode) { case WSAEADDRINUSE: AfxMessageBox("The specified address is already in use./n"); break; case WSAEADDRNOTAVAIL: AfxMessageBox("The specified address is not available from the local machine./n"); break; case WSAEAFNOSUPPORT: AfxMessageBox("Addresses in the specified family cannot be used with this socket./n"); break; case WSAECONNREFUSED: AfxMessageBox("The attempt to connect was forcefully rejected./n"); break; case WSAEDESTADDRREQ: AfxMessageBox("A destination address is required./n"); break; case WSAEFAULT: AfxMessageBox("The lpSockAddrLen argument is incorrect./n"); break; case WSAEINVAL: AfxMessageBox("The socket is already bound to an address./n"); break; case WSAEISCONN: AfxMessageBox("The socket is already connected./n"); break; case WSAEMFILE: AfxMessageBox("No more file descriptors are available./n"); break; case WSAENETUNREACH: AfxMessageBox("The network cannot be reached from this host at this time./n"); break; case WSAENOBUFS: AfxMessageBox("No buffer space is available. The socket cannot be connected./n"); break; case WSAENOTCONN: AfxMessageBox("The socket is not connected./n"); break; case WSAENOTSOCK: AfxMessageBox("The descriptor is a file, not a socket./n"); break; case WSAETIMEDOUT: AfxMessageBox("The attempt to connect timed out without establishing a connection. /n"); break; default: TCHAR szError[256]; wsprintf(szError, "OnConnect error: %d", nErrorCode); AfxMessageBox(szError); break; } } CAsyncSocket::OnConnect(nErrorCode); }

3、OnReceive函数

/************************************************************************/ /*函数名称:OnReceive /*功能描述:通知Socket可以调用成员函数Receive接收数据 /*函数参数:nErrorCode——标志发生在套接字上的最近错误,0表示该函数成功执行; /* WSAENETDOWN表示该函数执行失败。 /*返回结果:void /************************************************************************/ void CClientSocket::OnReceive(int nErrorCode) { m_szReceBuf = new char[MAXSOCKBUF];//申请内存 m_nLength = Receive((void *) m_szReceBuf, MAXSOCKBUF, 0);//接收数据 m_szReceBuf[m_nLength] = '/0'; SendMessage(m_dlg,WM_SOCKET_RECEIVE,(WPARAM)m_szReceBuf,m_nLength); memset(m_szReceBuf, 0, sizeof(m_szReceBuf));//重新初始化接收缓冲区 CAsyncSocket::OnReceive(nErrorCode); }

你可能感兴趣的:(网络课设总结(五)——利用CAsyncSocket进行异步通信)