源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

C++之WSAAsyncSelect模型实例

  • 时间:2020-08-03 02:44 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:C++之WSAAsyncSelect模型实例
本文实例讲述了C++中WSAAsyncSelect模型的用法。分享给大家供大家参考。具体实现方法如下: TCPServer.cpp源文件如下:
[u]复制代码[/u] 代码如下:
#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头文件如下:
[u]复制代码[/u] 代码如下:
#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源文件如下:
[u]复制代码[/u] 代码如下:
#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头文件如下:
[u]复制代码[/u] 代码如下:
#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++程序设计有所帮助。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部