• WSAAsyncSelect模型的小i例子


    一个异步模型的聊天程序

    服务器端:

    自定义消息(放在StdAfx.h文件里面即可)

    #define WM_SOCKET WM_USER + 1

    然后注册消(在VS2012里面可以自动完成注册和映射 )

    afx_msg LRESULT OnSocket(WPARAM wParam, LPARAM lParam);

    然后写上 映射

    ON_MESSAGE(WM_SOCKET, &CChatDlg::OnSocket)

     对话框的头文件代码

    // CChatDlg 对话框
    class CChatDlg : public CDialogEx
    {
    // 构造
    public:
        CChatDlg(CWnd* pParent = NULL);    // 标准构造函数
    
    // 对话框数据
        enum { IDD = IDD_MY_DIALOG };
    
        protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
    
    
    // 实现
    protected:
        HICON m_hIcon;
    
        // 生成的消息映射函数
        virtual BOOL OnInitDialog();
        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        DECLARE_MESSAGE_MAP()
    
    public:
        CString m_recv;
        CString m_send;
    public:
        SOCKET serverSocket;
        SOCKET sAccept; 
        struct sockaddr_in serverAddress;
        char recvBuff[1024];
        char sendBuff[1024];
        sockaddr_in clientAddr;
    public:
        bool initSocket();
        bool recvData();
    protected:
        afx_msg LRESULT OnSocket(WPARAM wParam, LPARAM lParam);
    public:
        afx_msg void OnBnClickedButtonSend();
    };

    然后cpp文件

    bool CChatDlg::initSocket()
    {
        WSADATA wsa;
        if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){
            MessageBox(_T("初始化套接字错误!"));
            return false;
        }
    
        if((serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
            MessageBox(_T("创建套接字失败!"));
            return false;
        }
        if (WSAAsyncSelect(serverSocket, this->m_hWnd, WM_SOCKET, FD_ACCEPT)==SOCKET_ERROR)
        {
                MessageBox(_T("WSAAyncSelect error!"));
        }
        memset(&serverAddress,0,sizeof(sockaddr_in));
        serverAddress.sin_family=AF_INET;
        serverAddress.sin_addr.S_un.S_addr = INADDR_ANY;
        serverAddress.sin_port = htons(6666);
    
        if(bind(serverSocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){
            MessageBox(_T("套接字绑定到端口失败!"));
            return false;
        }
        if (listen(serverSocket, 10)==SOCKET_ERROR)
        {
            MessageBox(_T("监听失败!"));
            return false;
        }
        int len = sizeof(serverAddress);
        //if((sAccept==accept(serverSocket, (sockaddr *)&serverAddress, &len)!=INVALID_SOCKET)) 
        //    MessageBox(_T("success!"));
        return true;
    
    }
    
    
    afx_msg LRESULT CChatDlg::OnSocket(WPARAM wParam, LPARAM lParam)
    {
     switch(WSAGETSELECTEVENT(lParam))  
            {  
            case FD_ACCEPT://接受客户端连接请求。  
                {  
                    int len = sizeof(clientAddr);
                    sAccept=accept(serverSocket, (sockaddr *)&clientAddr, &len);
                    if(sAccept==INVALID_SOCKET)  
                    {
                        MessageBox(_T("accept error!"));
                        break;
                    }
                    if (WSAAsyncSelect(sAccept, m_hWnd, WM_SOCKET, FD_READ|FD_CLOSE)==SOCKET_ERROR)
                    {
                        CString temp;
                        temp.Format(_T("%d"), WSAGetLastError());
                        MessageBox(temp);
                        MessageBox(_T("WSAAyncSelect error!"));
                    }
                    MessageBox(_T("success!"));
                    //在新接受的套接字发生FD_READ,FD_WRITE,FD_CLOSE网络事件发生,发送WM_SOCKET消息;  
                }  
                break;  
            case FD_READ://可读,接收数据。  
                {  
                    MessageBox(_T("read!"));
                    if (recvData())
                        UpdateData(false);
                    
                }  
                break;  
            case FD_CLOSE://对方关闭套接字连接。  
                {  
                   closesocket(sAccept);
                   WSACleanup(); 
                }  
                break;  
            default:  
                break;  
            }  
        return 0;
    }
    bool CChatDlg::recvData()
    {
        CString temp;
        int recvLen = 0;
        int len = 0;
        while (1)
        {
            len = recv(sAccept, recvBuff+recvLen, 100, 0);
            if (len < 100)
                break;
            recvLen += len;
        }
        WCHAR wch[1000];
        int n = MultiByteToWideChar( //转换Unicode到Ansi 
        936, 
        0, 
        recvBuff, 
        -1, 
        wch, //转换到缓冲区中 
        100000 //最多个字节 
        );
        m_recv += _T("client:
    ");
        m_recv+=wch;
        return true;
    }
    
    
    
    void CChatDlg::OnBnClickedButtonSend()
    {
        UpdateData(true);
        
        USES_CONVERSION; //定义后才能使用T2A
        sprintf_s(sendBuff,1024,"%s
    ",T2A(m_send));
        int err = send(sAccept, sendBuff, strlen(sendBuff), 0);
        if (SOCKET_ERROR == err)
        {
            MessageBox(_T("send error!"));
        }
        m_recv+=_T("server:
    ");
        m_recv+=m_send;
        m_recv+=_T("
    ");
        m_send = _T("");
        UpdateData(false);
    }

    WSAAsyncSelect函数在服务器时,要在bind函数之前使用,在客户端在connect函数之前,客户端的不同之处就是就是没有fd_accept这个事件,直接 fd_read事件即可。

  • 相关阅读:
    操作串口通信类(IO.Ports)SerialPort
    TreeView的数据源绑定—采用sqlite作为数据源,实现对treeview控件进行增删改查
    (Easy)打开指定的文件
    TreeView的数据源绑定—采用XML作为数据源,实现对treeview进行增删改查,之后回写XML文档
    linux sort,uniq,cut,wc命令详解
    轻快的VIM(六):恢复
    Python 常用模块大全(整理)
    定位oracle实例的当前跟踪文件名及路径
    查看session io
    查看pga使用
  • 原文地址:https://www.cnblogs.com/MyselfDancing/p/3695468.html
Copyright © 2020-2023  润新知