本文实例讲述了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++中WSAAsyncSelect模型的用法例程相关推荐

  1. Java 中的 XML:Java 文档模型的用法

    Java 中的 XML:Java 文档模型的用法 英文原文 内容: 代码对比 DOM JDOM dom4j Electric XML XPP 结束语 下一次... 参考资料 关于作者 对本文的评价 相 ...

  2. WinSock I/O 模型 -- WSAAsyncSelect 模型

    简介 WSAAsyncSelect 模型也是 WinSock 中常见的异步 I/O 模型. 使用这个模型,网络应用程序通过接收以 Windows 消息为基础的网络事件通知来处理网络请求. 这篇文章我们 ...

  3. WSAAsyncSelect模型

    Winsock提供了一个有用的异步I / O模型.利用这个模型,应用程序可在一个套接字上, 接收以Windows消息为基础的网络事件通知.具体的做法是在建好一个套接字后,调用 WSAAsyncSele ...

  4. 详细解析WSAAsyncSelect模型

    介绍 WinSock是Windows提供的包含了一系列网络编程接口的套接字程序库.在这篇文章中,我们将介绍如何把它的非阻塞模式引入到应用程序中. 阻塞模式WinSock.下述伪代码给出了阻塞模式下Wi ...

  5. C# API中的模型和它们的接口设计

    \ 关键要点 \\ 可变模型应该具备自我验证的能力,并实现验证接口.\\t 在共享对象时(特别是在跨线程共享时),考虑使用不可变模型.\\t 考虑支持MVVM风格UI的单层和多层撤消.\\t 在实现属 ...

  6. MVVM架构~knockoutjs系列之从Knockout.Validation.js源码中学习它的用法

    说在前 有时,我们在使用一个插件时,在网上即找不到它的相关API,这时,我们会很抓狂的,与其抓狂,还不如踏下心来,分析一下它的源码,事实上,对于JS这种开发语言来说,它开发的插件的使用方法都在它的源码 ...

  7. ASP.NET Core MVC 模型绑定用法及原理

    前言 查询了一下关于 MVC 中的模型绑定,大部分都是关于如何使用的,以及模型绑定过程中的一些用法和概念,很少有关于模型绑定的内部机制实现的文章,本文就来讲解一下在 ASP.NET Core MVC ...

  8. 基于WSAAsyncSelect模型实现的聊天室图形客户端

    对应的Linux服务器为:http://blog.csdn.net/microtong/archive/2009/12/12/4989902.aspx 头文件ClientDlg.h [cpp] vie ...

  9. tensorflow中batch normalization的用法

    转载网址:如果侵权,联系我删除 https://www.cnblogs.com/hrlnw/p/7227447.html https://www.cnblogs.com/eilearn/p/97806 ...

最新文章

  1. 字符串扩展_JAVA
  2. Sentinel-Dashboard 与 apollo 规则的相互同步
  3. Android Studio运行报错:无法访问XXX......请删除该文件或确保该文件位于正确的类路径子目录中
  4. 索引-python核心技术-pyhui版
  5. matlab中-psi_建议收藏 | 生物信息学中的可变剪切,这些内容你了解吗?
  6. arcgis javascript api 事件的监听及移除
  7. python输入错误提示再次输入_Python实现用户登录并且输入错误三次后锁定该用户...
  8. XSS-Game Level 4
  9. 4g伪基站如何实现的
  10. Jersey入门教程
  11. 华为商业级AC6005+AP3030DN无线WIFI组网
  12. 2019计算机四级网络工程师大纲,计算机四级《网络工程师》考试大纲
  13. 公测与奥运同行,云服务总线CSB:“连”无边界
  14. squid FATAL: Received Segment Violation...dying.
  15. 实例011阳阳买苹果
  16. JTopo添加动态连线
  17. java学生成绩管理系统类图,学生成绩管理系统的分析及设计-应用UML建模
  18. 第一个爬虫-爬取搜狗的一整张网页
  19. 零基础小白,如何入门计算机视觉?
  20. Idea工具的各种查找快捷键

热门文章

  1. android壁纸选择器,Android 图片选择器
  2. mysql删除数据不会减少存储占用_Mysql单文件存储删除数据文件容量不会减少的bug与解决方法...
  3. onclick 调用php,AJAX调用PHP简单应用
  4. 嵌入式牛人 | 这些单片机编程思想超硬核
  5. java 静态类 静态方法_JAVA的静态变量、静态方法、静态类
  6. java 成员变量的初始化_Java类变量和成员变量初始化过程
  7. mysql connect返回值_mysql_connect
  8. qt 关闭窗口的槽函数_勇哥的VC++应用框架学习之QT(1) 信号槽、按钮控件、opencv读取显示图片...
  9. asp.net 调用本地php,.NET_Asp.net获取服务器指定文件夹目录文件并提供下载的方法,本文实例讲述了Asp.net获取服务 - phpStudy...
  10. 微型计算机的主要硬件以及技术指标,微型计算机主要技术指标