2023年7月17日发(作者:)
基于MFC的socket编程⽹络编程1、windows 套接字编程(开放的⽹络编程接⼝)添加头⽂件#include2、套接字及其分类socket分为两种:(1)数据报socket:⽆连接套接字,可向指定的socket发送数据报消息,也可从指定的socket接收消息,提供双向的⾯向记录的数据流。但不能保证数据传输的顺序,也不能保证传输的可靠性。(2)数据流socket:(例如电话呼叫),基于显式连接的套接字,通过没有记录的双向字节数据流,具有可靠的发送顺序,接收也是可靠的,适合处理⼤量数据的传输。3、客户端/服务器模型(C/S模型)⽹络编程常⽤的⼀种架构模型,将应⽤程序分为:(1)前端客户端组件:运⾏在⼯作站上,负责从⽤户接收数据,为服务器处理数据,并形成到服务器的连接。(2)后台服务器组件:等待客户端的连接,当服务器收到客户端的连接请求后,服务器会处理并返回客户端响应信息,客户端收到响应信息后,通过⽤户接⼝,呈现给⽤户.⽬前很多项⽬都设计为分布式程序,以提⾼应⽤程序的性能。设计的关键是程序的性能和可扩展性。4、⽹络字节顺序标准的⽹络字节序是采⽤⼤端模式,⽽Intel采⽤⼩端模式。若使⽤MFC 的socket编程,即服务器和客户端都使⽤MFC,则⽆需关⼼字节顺序。5、使⽤WinSock API 进⾏编程6、MFC对WinSock API 进⾏了封装。提供了两个类:(1)类CAsynSocket⼀对⼀地封装了WinSock API。(2)类CSocket提供以CArchive对象中序列化数据的Socket功能。使⽤CSocket类,必须创建CSocket对象,使⽤对象底层的Socket句柄。对客户端使⽤默认参数调⽤create()⽅法就好,对服务器socket对象,必须在create()⽅法中指定IP地址和端⼝。下⾯是使⽤MFC socket编程的⼀个简单例⼦服务器端程序:(1)创建服务器(2)连接请求连接的客户端(3)与客户端进⾏数据传输(发送和接收)(4)客户端断开服务器界⾯如下图所⽰: 部分代码:/*说明:本函数⽤于打开或关闭服务器,主要⽤到Create函数和Listen函数⽤于创建服务器和监听客户端。其中端⼝号从编辑框获取,应⽤程序的可⽤端⼝范围是1024-65535。*/void CPhoneServerDlg::OnBnClickedstartserver(){ // TODO: 在此添加控件通知处理程序代码 if (m_connect) { delete listenSocket; listenSocket = NULL; m_connect = false; SetDlgItemText(IDC_startserver, _T("打开服务器")); UpdateEvent(_T("系统关闭服务器")); return; } listenSocket = new CSerSocket(); listenSocket->m_pDlg = this; // 指定对话框为主对话框,不能少了这句 UpdateData(true); if (!listenSocket->Create(m_port)) // 创建服务器的套接字,IP地址默认本机IP { AfxMessageBox(_T("创建套接字错误!")); listenSocket->Close(); return; } if (!listenSocket->Listen()) { AfxMessageBox(_T("监听失败!")); listenSocket->Close(); return; } m_connect = true; SetDlgItemText(IDC_startserver, _T("关闭服务器")); UpdateEvent(_T("系统打开服务器"));}/*说明:本函数在CServerSocket类中的OnAccept消息中调⽤,⽤于响应⽤户连接服务器的请求,主要函数为Accept,当连接成功后,通过链表m_clientList保存新⽤户,更新⽇志,向新⽤户发送“Hello”表⽰欢迎。*/void CPhoneServerDlg::AddClient(){ CSerSocket *pSocket = new CSerSocket; pSocket->m_pDlg = this; listenSocket->Accept(*pSocket); pSocket->AsyncSelect(FD_READ | FD_WRITE | FD_CLOSE); m_l(pSocket); m_usercount = m_nt(); UpdateEvent(_T("⽤户连接服务器")); SendMSG(_T("hello"));}/*本函数在CServerSocket类中的OnClose消息中调⽤,⽤到POSITION结构,查找存储⽤户中哪位⽤户下线了,将下线⽤户释放,从链表中删除,并更新⽇志。*/void CPhoneServerDlg::RemoveClient(CSerSocket *pSocket){ POSITION npos = m_dPosition(); POSITION nTmpPos = npos; while (npos) { CSerSocket *pSocketItem = (CSerSocket *)m_t(npos); if (pSocketItem->m_hSocket == pSocket->m_hSocket) { pSocketItem->Close(); delete pSocketItem; m_At(nTmpPos); m_usercount = m_nt(); UpdateData(false); UpdateEvent(_T("⽤户离开")); return; } nTmpPos = npos; }}/*说明:本函数在CServerSocket类中的OnReceive消息中调⽤,⽤于处理接收到的数据并控制电脑,并将数据转发给所有⽤户(类似于群消息),通过CSocket类的GetPeerName函数可以获取⽤户的IP和端⼝号。*/void CPhoneServerDlg::RecvData(CSerSocket *pSocket){ char *pData = NULL; pData = new char[1024]; memset(pData, 0, sizeof(char) * 1024); UCHAR leng = 0; CString str; if (pSocket->Receive(pData, 1024, 0) != SOCKET_ERROR) { str = pData; ControlPC(str); SendMSG(str); } delete pData; pData = NULL;}/*说明:本函数在所有需要更新⽇志的地⽅都有调⽤,⽅便服务器记录⽤户的登录和退出事件。*/void CPhoneServerDlg::UpdateEvent(CString str){ CString string; CTime time = CTime::GetCurrentTime(); // 获取系统当前时间 str += _T("rn"); // ⽤于换⾏显⽰⽇志 string = (_T("%Y/%m/%d %H:%M:%S ")) + str; // 格式化当前时间 int lastLine = m_dex(m_eCount() - 1); //获取编辑框最后⼀⾏索引 m_(lastLine + 1, lastLine + 2, 0); //选择编辑框最后⼀⾏ m_eSel(string);}/*说明:本函数在发送函数SendMSG中调⽤,⽤于字符集的转换,将宽字符转换为多字符集,不经转换的话,接收⽅只能接收⼀个字节。*/BOOL CPhoneServerDlg::WChar2MByte(LPCWSTR srcBuff, LPSTR destBuff, int nlen){ int n = 0; n = WideCharToMultiByte(CP_OEMCP, 0, srcBuff, -1, destBuff, 0, 0, FALSE); if (nSend(pSend, gth()); } delete pSend;}
客户端界⾯如下:部分代码:void CPhoneClinetDlg::OnBnClickedconnect(){ // TODO: 在此添加控件通知处理程序代码 if (m_connect) // 如果已经连接,则断开服务器 { m_connect = false; pSock->Close(); delete pSock; pSock = NULL; m_dowTextW(_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_dowTextW(_T("断开服务器")); UpdateData(false); }}void CPhoneClinetDlg::OnBnClickedsend(){ // TODO: 在此添加控件通知处理程序代码 if (!m_connect)return; //未连接服务器则不执⾏ UpdateData(true); //获取界⾯数据 if (m_datasend != "") { char* pBuff = new char[m_gth() * 2]; memset(pBuff, 0, m_gth() * 2); WChar2MByte(m_fer(0), pBuff, m_gth() * 2); pSock->SendMSG(pBuff, m_gth() * 2); }}
发布者:admin,转转请注明出处:http://www.yc00.com/web/1689608165a270241.html
评论列表(0条)