本文实例讲述了C++中WSAAsyncSelect模型的用法。分享给大家供大家参考。具体实现方法如下:
TCPServer.cpp源文件如下:
#include "TCPServer.h" #include "resource.h" #define WM_SOCKET WM_USER+1 CMyApp theApp; BOOL CMyApp::InitInstance() { //初始化套接字 WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2,0); ::WSAStartup(wVersionRequested, &wsaData); //显示对话框 CMainDialog dlg; m_pMainWnd = &dlg; dlg.DoModal(); //释放套接字 ::WSACleanup(); return FALSE; } //CMainDialog CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG,pParentWnd) { } BEGIN_MESSAGE_MAP(CMainDialog, CDialog) ON_BN_CLICKED(IDC_START, OnStart) ON_BN_CLICKED(IDC_CLEAR, OnClear) ON_MESSAGE(WM_SOCKET, OnSocket) END_MESSAGE_MAP() void CMainDialog::OnCancel() { this->CloseAllSocket(); CDialog::OnCancel(); } BOOL CMainDialog::OnInitDialog() { CDialog::OnInitDialog(); //设置图标 SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE); //创建状态栏并设置其属性 m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0,0,0,0), this, 101); m_bar.SetBkColor(RGB(0xa6, 0xca, 0xfa)); int arWidth[]={200,-1}; m_bar.SetParts(2, arWidth); m_bar.SetText("windows程序设计", 1, 0); m_bar.SetText("空闲", 0, 0); //关联列表控件 m_listInfo.SubclassDlgItem(IDC_LIST, this); //初始化套接字和连接列表 m_socket = INVALID_SOCKET; m_nClient = 0; //取得本机IP,在状态栏中显示 char szHostName[MAX_PATH] = {0}; ::gethostname(szHostName, MAX_PATH); hostent *pHost = gethostbyname(szHostName); if (pHost != NULL) { CString strIP; in_addr* addr = (in_addr*)*pHost->h_addr_list; strIP.Format("本机IP:%s",inet_ntoa(addr[0])); m_bar.SetText(strIP, 0, 0); } return TRUE; } BOOL CMainDialog::CreateAndListen(int nPort) { if (m_socket == INVALID_SOCKET) { ::closesocket(m_socket); } //创建套接字 m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_socket == INVALID_SOCKET) { return FALSE; } //绑定端口 sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(nPort); //sin.sin_addr.S_un.S_addr = INADDR_ANY; sin.sin_addr.s_addr = INADDR_ANY; int nErr = GetLastError(); if (::bind(m_socket, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) { nErr = GetLastError(); return FALSE; } ::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE|FD_READ); //进入监听模式 ::listen(m_socket, 5); return TRUE; } BOOL CMainDialog::AddClient(SOCKET s) { if (m_nClient < MAX_SOCKET) { m_arClient[m_nClient++] = s; return TRUE; } return FALSE; } void CMainDialog::RemoveClient(SOCKET s) { BOOL bFound = FALSE; int i; for (i=0;i<m_nClient;i++) { if (m_arClient[i] == s) { bFound = TRUE; break; } } //找到 if (bFound) { m_nClient--; for (int j=i;j<m_nClient;j++) { m_arClient[j] = m_arClient[j+1]; } } } void CMainDialog::CloseAllSocket() { if (m_socket != INVALID_SOCKET) { ::closesocket(m_socket); m_socket = INVALID_SOCKET; } for (int i=0;i<m_nClient;i++) { ::closesocket(m_arClient[i]); } m_nClient = 0; } void CMainDialog::OnStart() { if (m_socket == INVALID_SOCKET) //开启服务 { CString strPort; GetDlgItem(IDC_PORT)->GetWindowText(strPort); int nPort = atoi(strPort); if (nPort < 1 || nPort >65535) { MessageBox("port error"); return; } //创建套接字 if (!this->CreateAndListen(nPort)) { MessageBox("create socket error"); return; } //设置控件状态 GetDlgItem(IDC_START)->SetWindowTextA("停止服务"); m_bar.SetText("正在监听...", 0, 0); GetDlgItem(IDC_PORT)->EnableWindow(FALSE); } else //关闭服务 { CloseAllSocket(); GetDlgItem(IDC_START)->SetWindowTextA("开启服务"); m_bar.SetText("空闲", 0, 0); GetDlgItem(IDC_PORT)->EnableWindow(TRUE); } return ; } void CMainDialog::OnClear() { m_listInfo.ResetContent(); return ; } long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam) { //得到句柄 SOCKET s = wParam; //查看是否出错 if (WSAGETSELECTERROR(lParam)) { RemoveClient(s); ::closesocket(s); return 0; } //处理发生的事件 switch (WSAGETSELECTEVENT(lParam)) { case FD_ACCEPT: //监听到有套接字中有连接进入 { MessageBox("server:accept"); if (m_nClient < MAX_SOCKET) { SOCKET client = ::accept(s, NULL, NULL); this->AddClient(client); } else { MessageBox("too many connection"); } } break; case FD_CLOSE: { MessageBox("server:close"); RemoveClient(s); closesocket(s); } break; case FD_READ: //接收到对方发来的数据包 { MessageBox("server:read"); //得到对方的地址 sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); int nSockAddrLength = sizeof(sockAddr); ::getpeername(s, (sockaddr*)&sockAddr, &nSockAddrLength); int nPeerPort = ntohs(sockAddr.sin_port); CString strIP = inet_ntoa(sockAddr.sin_addr); // strIP //获得主机名称 DWORD dwIP = ::inet_addr(strIP); hostent* pHost = ::gethostbyaddr((LPSTR)&dwIP, 4, AF_INET); char szHostName[256]={0}; strncpy(szHostName, pHost->h_name, 256); //得到网络数据 char szContent[1024]={0}; ::recv(s, szContent, 1024, 0); //显示 CString strItem = CString(szHostName) + "[" + strIP + "]:" + CString(szContent); m_listInfo.InsertString(0, strItem); } break; } return 0; }
TCPServer.h头文件如下:
#include <afxwin.h> #include <afxext.h> //CStatusBar #include <WinSock2.h> #include <afxcmn.h> #pragma comment(lib, "WS2_32.lib") #define MAX_SOCKET 56 //最大客户量 class CMyApp:public CWinApp { public: BOOL InitInstance(); }; //CMainDialog class CMainDialog:public CDialog { public: CMainDialog(CWnd* pParentWnd=NULL); protected: virtual BOOL OnInitDialog(); virtual void OnCancel(); //开启或停止服务 afx_msg void OnStart(); afx_msg void OnClear(); afx_msg long OnSocket(WPARAM wParam, LPARAM lParam); BOOL CreateAndListen(int nPort); //向客户连接列表中加一个客户 BOOL AddClient(SOCKET s); //从客户连接列表中移除一个客户 void RemoveClient(SOCKET s); //关闭所有连接 void CloseAllSocket(); protected: SOCKET m_socket; //两个子窗口控件 CListBox m_listInfo; CStatusBarCtrl m_bar; //客户连接列表 SOCKET m_arClient[MAX_SOCKET]; //套接字列表 int m_nClient; //上述数组的大小 DECLARE_MESSAGE_MAP() };
TCPClient.cpp源文件如下:
#include "TCPClient.h" #include "resource.h" #define WM_SOCKET WM_USER+1 CMyApp theApp; BOOL CMyApp::InitInstance() { //初始化套接字 WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2,0); ::WSAStartup(wVersionRequested, &wsaData); //显示对话框 CMainDialog dlg; m_pMainWnd = &dlg; dlg.DoModal(); //释放套接字 ::WSACleanup(); return FALSE; } //CMainDialog CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG,pParentWnd) { } BEGIN_MESSAGE_MAP(CMainDialog, CDialog) ON_BN_CLICKED(IDC_CONNECT, OnConnect) ON_BN_CLICKED(IDC_SEND, OnSend) ON_MESSAGE(WM_SOCKET, OnSocket) END_MESSAGE_MAP() void CMainDialog::OnCancel() { CDialog::OnCancel(); } BOOL CMainDialog::OnInitDialog() { CDialog::OnInitDialog(); //设置图标 SetIcon(theApp.LoadIconA(IDI_MAIN), FALSE); //关联控件 m_edit_text.SubclassDlgItem(IDC_EDIT_CONTENT, this); //状态栏 m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0, 0, 0,0), this, NULL); int nWidth[]={100,-1}; m_bar.SetParts(2, nWidth); m_bar.SetText("windows程序设计", 1, 0); m_bar.SetText("空闲", 0, 0); GetDlgItem(IDC_ADDR)->SetWindowTextA("192.168.19.143"); GetDlgItem(IDC_PORT)->SetWindowTextA("9999"); // m_socket = INVALID_SOCKET; return TRUE; } void CMainDialog::AddStringToList(CString strText) { CString strContent; GetDlgItem(IDC_EDIT_CONTENT)->GetWindowText(strContent); GetDlgItem(IDC_EDIT_CONTENT)->SetWindowText(strContent+strText); } long CMainDialog::OnSocket(WPARAM wParam, LPARAM lParam) { SOCKET s = wParam; if (WSAGETSELECTERROR(lParam)) { ::closesocket(m_socket); m_socket = INVALID_SOCKET; return 0; } switch (WSAGETSELECTEVENT(lParam)) { case FD_READ: { MessageBox("client:read"); char szText[1024]={0}; ::recv(s, szText, 1024, 0); AddStringToList(CString(szText)+"\r\n"); } break; case FD_CONNECT: { MessageBox("client:connect"); GetDlgItem(IDC_CONNECT)->SetWindowTextA("断开连接"); GetDlgItem(IDC_ADDR)->EnableWindow(FALSE); GetDlgItem(IDC_PORT)->EnableWindow(FALSE); GetDlgItem(IDC_TEXT)->EnableWindow(TRUE); GetDlgItem(IDC_SEND)->EnableWindow(TRUE); m_bar.SetText("已经连接到服务器", 0, 0); } break; case FD_CLOSE: { MessageBox("client:close"); OnConnect(); } break; } return 0; } BOOL CMainDialog::Connect(LPCTSTR pszRemoteAddr, u_short nPort) { //创建套接字 m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == m_socket) { return FALSE; } ::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CONNECT|FD_CLOSE); ULONG uAddr = ::inet_addr(pszRemoteAddr); if (uAddr == INADDR_NONE) { //不是IP地址,就认为是主机名称 //从主机名得到IP hostent* pHost = ::gethostbyname(pszRemoteAddr); if (pHost == NULL) { ::closesocket(m_socket); m_socket = INVALID_SOCKET; return FALSE; } uAddr = ((struct in_addr*)*(pHost->h_addr_list))->s_addr; } //填写服务器信息 sockaddr_in remote; remote.sin_family = AF_INET; remote.sin_addr.S_un.S_addr = uAddr; remote.sin_port = ::htons(nPort); //连接 ::connect(m_socket, (sockaddr*)&remote, sizeof(sockaddr)); return TRUE; } void CMainDialog::OnConnect() { if (INVALID_SOCKET == m_socket) //连接服务器 { CString strAddr; GetDlgItem(IDC_ADDR)->GetWindowText(strAddr); if (strAddr.IsEmpty()) { MessageBox("the servers IP is empty"); return; } CString strPort; GetDlgItem(IDC_PORT)->GetWindowTextA(strPort); int nPort = atoi(strPort); if (nPort < 1 || nPort > 65535) { MessageBox("port error"); return; } if (Connect(strAddr, nPort) == FALSE) { MessageBox("connect to servers error..."); return; } //设置用户界面 GetDlgItem(IDC_CONNECT)->SetWindowText("取消"); m_bar.SetText("正在连接..", 0, 0); } else //断开服务器 { ::closesocket(m_socket); m_socket = INVALID_SOCKET; //设置用户界面 GetDlgItem(IDC_CONNECT)->SetWindowTextA("连接服务器"); m_bar.SetText("空闲", 0, 0); GetDlgItem(IDC_ADDR)->EnableWindow(TRUE); GetDlgItem(IDC_PORT)->EnableWindow(TRUE); GetDlgItem(IDC_SEND)->EnableWindow(FALSE); GetDlgItem(IDC_TEXT)->EnableWindow(FALSE); } //this->Connect(szAddr, ) } void CMainDialog::OnSend() { CString strSendContent; GetDlgItem(IDC_TEXT)->GetWindowTextA(strSendContent); ::send(m_socket, strSendContent, strSendContent.GetLength(), 0); GetDlgItem(IDC_TEXT)->SetWindowTextA(""); }
TCPClient.h头文件如下:
#include <afxwin.h> #include <afxext.h> //CStatusBar #include <WinSock2.h> #include <afxcmn.h> #pragma comment(lib, "WS2_32.lib") #define MAX_SOCKET 56 //最大客户量 class CMyApp:public CWinApp { public: BOOL InitInstance(); }; //CMainDialog class CMainDialog:public CDialog { public: CMainDialog(CWnd* pParentWnd=NULL); protected: virtual BOOL OnInitDialog(); virtual void OnCancel(); ////开启或停止服务 //afx_msg void OnStart(); afx_msg void OnSend(); afx_msg long OnSocket(WPARAM wParam, LPARAM lParam); void OnConnect(); BOOL Connect(LPCTSTR pszRemoteAddr, u_short nPort); SOCKET m_socket; // 控件 CStatusBarCtrl m_bar; CEdit m_edit_text; void AddStringToList(CString strText); //BOOL CreateAndListen(int nPort); ////向客户连接列表中加一个客户 //BOOL AddClient(SOCKET s); ////从客户连接列表中移除一个客户 //void RemoveClient(SOCKET s); ////关闭所有连接 //void CloseAllSocket(); DECLARE_MESSAGE_MAP() };
希望本文所述对大家的C++程序设计有所帮助。
本文向大家介绍C++中I/O模型之select模型实例,包括了C++中I/O模型之select模型实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C++中I/O模型的select模型用法。分享给大家供大家参考。具体实现方法如下: 效果如下图所示: 希望本文所述对大家的C++程序设计有所帮助。
本文向大家介绍C++设计模式之简单工厂模式实例,包括了C++设计模式之简单工厂模式实例的使用技巧和注意事项,需要的朋友参考一下 问题描述 之前在公司做了一个windows 8平台的阅读器。首先,需要将电子书中的内容渲染到屏幕上,而电子书每一页都包含各种各样的内容,比如:图形、图像和文字等等;不同的内容,就是不同的对象;在将不同的内容渲染到屏幕上之前,就需要new操作,建立不同的对象,然后再在屏幕上
本文向大家介绍C#设计模式之单例模式实例讲解,包括了C#设计模式之单例模式实例讲解的使用技巧和注意事项,需要的朋友参考一下 前言 最近开始花点心思研究下设计模式,主要还是让自己写的代码可重用性高、保证代码可靠性。所谓设计模式,我找了下定义:是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工
我有类似于这个问题用例 我想检查什么类型的实例变量存储在参数中而不引发异常 我想做的是这样的事情 我如何改变这个实现,使它允许我窥视什么类型的参数是持有的 谢谢你的回答,还有几点 我是C++11所以不能使用variant或any 有没有标准的方法。我想要的是一个实例变量的类,可以是多种类型(有界的),并在阅读它时,检查它是什么类型
本文向大家介绍C#基础之泛型委托实例教程,包括了C#基础之泛型委托实例教程的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#中泛型委托的用法,并以示例形式较为详细的进行了用法分析。分享给大家供大家参考之用。具体如下: 首先,泛型委托是委托的一种特殊形式,虽然感觉看上去比较怪异,其实在使用的时候跟委托差不多,不过泛型委托更具有类型通用性。 就拿C#里最常见的委托EventHandler打比
本文向大家介绍C#设计模式之观察者模式实例讲解,包括了C#设计模式之观察者模式实例讲解的使用技巧和注意事项,需要的朋友参考一下 前言 最近开始花点心思研究下设计模式,主要还是让自己写的代码可重用性高、保证代码可靠性。所谓设计模式,我找了下定义:是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软