Windows Practice_作业 Easy QQ的实现

来源:互联网 发布:java 按键监听 编辑:程序博客网 时间:2024/05/21 09:10

QQ原理

对于qq这样的聊天软件来说,简单的来讲,它有一个服务端、多个客户端,因为服务端只有一个,所以也就没什么区别,而所有的客户端也是一模一样。
每个客户端只能通过向服务端发送消息,服务端通过解析,从而决定下一步怎样做。
比如一个客户端1想给客户端2发送一条“Hello”的消息,服务器收到后,就会将这条消息发送给客户端2(这里所说的都是在线的,不在线的情况暂不考虑)。

WSAAsyncSelect使用示例

这里写图片描述

// WSASelectDlg.h : 头文件//#pragma once// CWSASelectDlg 对话框class CWSASelectDlg : public CDialogEx{// 构造public:    CWSASelectDlg(CWnd* pParent = NULL);    // 标准构造函数    ~CWSASelectDlg();// 对话框数据#ifdef AFX_DESIGN_TIME    enum { IDD = IDD_WSASELECT_DIALOG };#endif    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()private:    SOCKET m_socket;public:    afx_msg void OnBnClickedButtonStartService();protected:    afx_msg LRESULT OnSocket(WPARAM wParam, LPARAM lParam);};
// WSASelectDlg.cpp : 实现文件//#include "stdafx.h"#include "WSASelect.h"#include "WSASelectDlg.h"#include "afxdialogex.h"#include <WinSock2.h>#pragma comment(lib, "ws2_32.lib")#ifdef _DEBUG#define new DEBUG_NEW#endif#define WM_SOCKET   (WM_USER+1)// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx{public:    CAboutDlg();// 对话框数据#ifdef AFX_DESIGN_TIME    enum { IDD = IDD_ABOUTBOX };#endif    protected:    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现protected:    DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){    CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)END_MESSAGE_MAP()// CWSASelectDlg 对话框CWSASelectDlg::CWSASelectDlg(CWnd* pParent /*=NULL*/)    : CDialogEx(IDD_WSASELECT_DIALOG, pParent){    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}CWSASelectDlg::~CWSASelectDlg(){    WSACleanup();}void CWSASelectDlg::DoDataExchange(CDataExchange* pDX){    CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CWSASelectDlg, CDialogEx)    ON_WM_SYSCOMMAND()    ON_WM_PAINT()    ON_WM_QUERYDRAGICON()    ON_BN_CLICKED(IDC_BUTTON_START_SERVICE, &CWSASelectDlg::OnBnClickedButtonStartService)    ON_MESSAGE(WM_SOCKET, &CWSASelectDlg::OnSocket)END_MESSAGE_MAP()// CWSASelectDlg 消息处理程序BOOL CWSASelectDlg::OnInitDialog(){    CDialogEx::OnInitDialog();    // 将“关于...”菜单项添加到系统菜单中。    // IDM_ABOUTBOX 必须在系统命令范围内。    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);    ASSERT(IDM_ABOUTBOX < 0xF000);    CMenu* pSysMenu = GetSystemMenu(FALSE);    if (pSysMenu != NULL)    {        BOOL bNameValid;        CString strAboutMenu;        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);        ASSERT(bNameValid);        if (!strAboutMenu.IsEmpty())        {            pSysMenu->AppendMenu(MF_SEPARATOR);            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);        }    }    // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动    //  执行此操作    SetIcon(m_hIcon, TRUE);         // 设置大图标    SetIcon(m_hIcon, FALSE);        // 设置小图标    // TODO: 在此添加额外的初始化代码    WSAData wsaData;    WSAStartup(MAKEWORD(2, 2), &wsaData);    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE}void CWSASelectDlg::OnSysCommand(UINT nID, LPARAM lParam){    if ((nID & 0xFFF0) == IDM_ABOUTBOX)    {        CAboutDlg dlgAbout;        dlgAbout.DoModal();    }    else    {        CDialogEx::OnSysCommand(nID, lParam);    }}// 如果向对话框添加最小化按钮,则需要下面的代码//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,//  这将由框架自动完成。void CWSASelectDlg::OnPaint(){    if (IsIconic())    {        CPaintDC dc(this); // 用于绘制的设备上下文        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);        // 使图标在工作区矩形中居中        int cxIcon = GetSystemMetrics(SM_CXICON);        int cyIcon = GetSystemMetrics(SM_CYICON);        CRect rect;        GetClientRect(&rect);        int x = (rect.Width() - cxIcon + 1) / 2;        int y = (rect.Height() - cyIcon + 1) / 2;        // 绘制图标        dc.DrawIcon(x, y, m_hIcon);    }    else    {        CDialogEx::OnPaint();    }}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CWSASelectDlg::OnQueryDragIcon(){    return static_cast<HCURSOR>(m_hIcon);}void CWSASelectDlg::OnBnClickedButtonStartService(){    m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    sockaddr_in addr;    addr.sin_family = AF_INET;    addr.sin_port = htons(10086);    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");    ::bind(m_socket, (sockaddr *)&addr, sizeof(sockaddr_in));    ::WSAAsyncSelect(m_socket, m_hWnd, WM_SOCKET, FD_ACCEPT);    ::listen(m_socket, 10);}afx_msg LRESULT CWSASelectDlg::OnSocket(WPARAM wParam, LPARAM lParam){    switch (WSAGETSELECTEVENT(lParam))    {    case FD_ACCEPT:    {        SOCKET s = ::accept(m_socket, nullptr, nullptr);        ::WSAAsyncSelect(s, m_hWnd, WM_SOCKET, FD_READ | FD_WRITE);        break;    }    default:        break;    }    return 0;}

Easy QQ分为以下几个模块
- 登录(包括注册,修改账号名,密码)
- 添加好友(查找好友)
- 发送消息
- 群聊
- 离线消息(如果时间充裕的话可以尝试实现)

阅读全文
1 0
原创粉丝点击