Visual Studio 2010/2013
创建一个项目,与服务器端类似,别忘了选择“windows套接字”。创建好以后设计对话框界面。2个按钮,1个用来连接或者断开服务器,另一个用来发送数据;2个编辑框,一个用来显示接收到的数据,另一个用来输入需要发送的数据。
编辑控件的属性,通过类向导添加相应的变量,双击按钮添加按钮按下处理事件。
添加客户端类CClientSocket,通过类向导添加OnReceive函数。
修改客户端类的头文件:/********************ClientSocket.h*********************/#pragma onceclass CClientSocket : public CSocket{public: CClientSocket(); virtual ~CClientSocket(); virtual void OnReceive(int nErrorCode); // 重写接收函数,通过类向导生成 BOOL SendMSG(LPSTR lpBuff, int nlen); // 发送函数,用于发送数据给服务器};
修改客户端类的源文件:/********************ClientSocket.cpp*********************/#include 'stdafx.h'#include 'PhoneClient.h'#include 'ClientSocket.h'#include 'PhoneClientDlg.h' CClientSocket::CClientSocket(){}CClientSocket::~CClientSocket(){} void CClientSocket::OnReceive(int nErrorCode){ // TODO: 在此添加专用代码和/或调用基类 char* pData = NULL; pData = new char[1024]; memset(pData, 0, sizeof(char)* 1024); UCHAR leng = 0; CString str; leng = Receive(pData, 1024, 0); str = pData;// 在编辑框中显示接收到的数据 ((CPhoneClientDlg*)theApp.GetMainWnd())->SetDlgItemTextW(IDC_DataReceive, str); delete pData; pData = NULL; CSocket::OnReceive(nErrorCode);} BOOL CClientSocket::SendMSG(LPSTR lpBuff, int nlen){ //生成协议头 if (Send(lpBuff, nlen) == SOCKET_ERROR) { AfxMessageBox(_T('发送错误!')); return FALSE; } return TRUE;}说明:当客户端接收到服务器端发的数据时会响应接收函数OnReceive,这里只是简单的将获取的信息显示在编辑框中。SendMSG函数用于向服务器发送消息,函数会在主对话框类中调用。
修改对话框类的头文件,添加相关函数声明以及必要的变量定义:bool m_connect;CClientSocket* pSock; // 客户端套接字指针对象BOOL WChar2MByte(LPCWSTR lpSrc, LPSTR lpDest, int nlen); //字符转换函数public:virtual BOOL PreTranslateMessage(MSG* pMsg); //防止按下enter、esc时退出程序
在对话框类的源文件中编写所有声明的函数,实现各项函数的功能。1、 连接服务器的按钮事件处理函数void CPhoneClientDlg::OnBnClickedConnect(){ if (m_connect) // 如果已经连接,则断开服务器 { m_connect = false; pSock->Close(); delete pSock; pSock = NULL; m_ConPC.SetWindowTextW(_T('连接服务器')); UpdateData(false); return; } else // 未连接,则连接服务器 { pSock = new CClientSocket(); if (!pSock->Create()) //创建套接字 { AfxMessageBox(_T('创建套接字失败!')); return; } } if (!pSock->Connect(_T('127.0.0.1'), port)) //连接服务器 { AfxMessageBox(_T('连接服务器失败!')); return; } else { m_connect = true; m_ConPC.SetWindowTextW(_T('断开服务器')); UpdateData(false); }}说明:本函数通过Create和Connect与服务器建立连接。由于在本机上测试,所以IP为127.0.0.1,实际应用时可以添加一个控件用于输入服务器的IP。端口号必须与服务器的一致,这里的port是一个常量:#define port 8000
2、 发送按钮的事件处理函数void CPhoneClientDlg::OnBnClickedSend(){ // TODO: 在此添加控件通知处理程序代码 if (!m_connect)return; //未连接服务器则不执行 UpdateData(true); //获取界面数据 if (m_DataSend != '') { char* pBuff = new char[m_DataSend.GetLength() * 2]; memset(pBuff, 0, m_DataSend.GetLength() * 2); WChar2MByte(m_DataSend.GetBuffer(0), pBuff, m_DataSend.GetLength() * 2); pSock->SendMSG(pBuff, m_DataSend.GetLength() * 2); }}说明:这里的SendMSG函数与服务器端的不一致,函数实体在CClientSocket类中以实现。WChar2MByte字符转换函数与服务器端的一致,在这不再赘述。
对话框的主要函数就是以上2个,一个用于连接和断开服务器,另一个用于发送数据。至于虚函数PreTeanslateMessage,其处理方法与服务器中介绍的一致。将服务器与客户端都编写好以后,就可以测试通讯效果,可以同时打开多个客户端,看看服务器如何处理。
这篇经验需要参考上一篇关于服务器端编程的经验
服务器端与客户端通过socket实现网络通讯