基于WSAAsyncSelect模型实现的聊天室图形客户端
来源:互联网 发布:nginx ab压力测试 编辑:程序博客网 时间:2024/06/05 06:10
对应的Linux服务器为:http://blog.csdn.net/microtong/archive/2009/12/12/4989902.aspx
头文件ClientDlg.h
- // ClientDlg.h : 头文件
- //
- #pragma once
- #include "afxcmn.h"
- #include "afxwin.h"
- #define WM_NETWORK WM_USER+100
- // CClientDlg 对话框
- class CClientDlg : public CDialog
- {
- // 构造
- public:
- CClientDlg(CWnd* pParent = NULL); // 标准构造函数
- // 对话框数据
- enum { IDD = IDD_CLIENT_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:
- CIPAddressCtrl m_ip;
- int m_port;
- CEdit m_allmsg;
- CString m_nickname;
- CString m_message;
- afx_msg void OnBnClickedConnect();
- // 服务器套接字
- SOCKET sock;
- struct sockaddr_in serverAddr;
- CString msg;
- LRESULT OnNetwork(WPARAM wParam, LPARAM lParam);
- void OnConnect(SOCKET s);
- void OnRead(SOCKET s);
- void OnCloseSocket(SOCKET s);
- afx_msg void OnBnClickedSend();
- afx_msg void OnBnClickedDisconnect();
- afx_msg void OnClose();
- afx_msg void OnBnClickedQuit();
- afx_msg void OnBnClickedChangeName();
- };
对话框源文件 ClientDlg.cpp
- // ClientDlg.cpp : 实现文件
- //
- #include "stdafx.h"
- #include "Client.h"
- #include "ClientDlg.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
- class CAboutDlg : public CDialog
- {
- public:
- CAboutDlg();
- // 对话框数据
- enum { IDD = IDD_ABOUTBOX };
- protected:
- virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
- // 实现
- protected:
- DECLARE_MESSAGE_MAP()
- };
- CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
- {
- }
- void CAboutDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- }
- BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
- END_MESSAGE_MAP()
- // CClientDlg 对话框
- CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
- : CDialog(CClientDlg::IDD, pParent)
- , m_port(8000)
- , m_nickname(_T("microtong"))
- , m_message(_T("hello"))
- {
- m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
- }
- void CClientDlg::DoDataExchange(CDataExchange* pDX)
- {
- CDialog::DoDataExchange(pDX);
- DDX_Control(pDX, IDC_IP, m_ip);
- DDX_Text(pDX, IDC_PORT, m_port);
- DDX_Control(pDX, IDC_ALLMESSAGE, m_allmsg);
- DDX_Text(pDX, IDC_NICKNAME, m_nickname);
- DDV_MaxChars(pDX, m_nickname, 30);
- DDX_Text(pDX, IDC_MESSAGE, m_message);
- DDV_MaxChars(pDX, m_message, 1024);
- }
- BEGIN_MESSAGE_MAP(CClientDlg, CDialog)
- ON_WM_SYSCOMMAND()
- ON_WM_PAINT()
- ON_WM_QUERYDRAGICON()
- //}}AFX_MSG_MAP
- ON_BN_CLICKED(IDC_CONNECT, &CClientDlg::OnBnClickedConnect)
- ON_BN_CLICKED(IDC_SEND, &CClientDlg::OnBnClickedSend)
- ON_BN_CLICKED(IDC_DISCONNECT, &CClientDlg::OnBnClickedDisconnect)
- ON_WM_CLOSE()
- ON_BN_CLICKED(IDC_QUIT, &CClientDlg::OnBnClickedQuit)
- ON_BN_CLICKED(IDC_CHANGENAME, &CClientDlg::OnBnClickedChangeName)
- ON_MESSAGE(WM_NETWORK,&CClientDlg::OnNetwork)
- END_MESSAGE_MAP()
- // CClientDlg 消息处理程序
- BOOL CClientDlg::OnInitDialog()
- {
- CDialog::OnInitDialog();
- // 将“关于...”菜单项添加到系统菜单中。
- // IDM_ABOUTBOX 必须在系统命令范围内。
- ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
- ASSERT(IDM_ABOUTBOX < 0xF000);
- CMenu* pSysMenu = GetSystemMenu(FALSE);
- if (pSysMenu != NULL)
- {
- CString strAboutMenu;
- strAboutMenu.LoadString(IDS_ABOUTBOX);
- if (!strAboutMenu.IsEmpty())
- {
- pSysMenu->AppendMenu(MF_SEPARATOR);
- pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
- }
- }
- // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
- // 执行此操作
- SetIcon(m_hIcon, TRUE); // 设置大图标
- SetIcon(m_hIcon, FALSE); // 设置小图标
- // TODO: 在此添加额外的初始化代码
- //为测试方便IP地址初始化为本机IP地址
- m_ip.SetAddress(127,0,0,1);
- return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
- }
- void CClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
- {
- if ((nID & 0xFFF0) == IDM_ABOUTBOX)
- {
- CAboutDlg dlgAbout;
- dlgAbout.DoModal();
- }
- else
- {
- CDialog::OnSysCommand(nID, lParam);
- }
- }
- // 如果向对话框添加最小化按钮,则需要下面的代码
- // 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
- // 这将由框架自动完成。
- void CClientDlg::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
- {
- CDialog::OnPaint();
- }
- }
- //当用户拖动最小化窗口时系统调用此函数取得光标显示。
- //
- HCURSOR CClientDlg::OnQueryDragIcon()
- {
- return static_cast<HCURSOR>(m_hIcon);
- }
- void CClientDlg::OnBnClickedConnect()
- {
- UpdateData(TRUE);
- DWORD ip;
- m_ip.GetAddress(ip);
- //初始化套接字DLL
- WSADATA wsa;
- if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){
- MessageBox("套接字初始化失败!");
- return;
- }
- //创建套接字
- if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
- MessageBox("创建套接字失败!");
- WSACleanup();
- return;
- }
- ZeroMemory(&serverAddr,sizeof(serverAddr));
- serverAddr.sin_family = AF_INET;
- serverAddr.sin_addr.S_un.S_addr = htonl(ip);
- serverAddr.sin_port = htons(m_port);
- //注册感兴趣的网络事件
- if(WSAAsyncSelect(sock, m_hWnd, WM_NETWORK, FD_CONNECT | FD_READ | FD_CLOSE)==SOCKET_ERROR){
- MessageBox("注册网络事件失败!");
- closesocket(sock);
- WSACleanup();
- }
- msg.Format("Connecting to %s:%d/n",inet_ntoa(serverAddr.sin_addr), ntohs(serverAddr.sin_port));
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(msg);
- if(connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr))==SOCKET_ERROR){
- int err = WSAGetLastError();
- if(err==WSAEWOULDBLOCK){
- msg.Format("Waiting....../n");
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(msg);
- }else{
- MessageBox("无法连接到服务器!");
- closesocket(sock);
- WSACleanup();
- }
- }
- GetDlgItem(IDC_DISCONNECT)->EnableWindow(TRUE);
- GetDlgItem(IDC_SEND)->EnableWindow(TRUE);
- GetDlgItem(IDC_CHANGENAME)->EnableWindow(TRUE);
- GetDlgItem(IDC_CONNECT)->EnableWindow(FALSE);
- GetDlgItem(IDC_IP)->EnableWindow(FALSE);
- GetDlgItem(IDC_PORT)->EnableWindow(FALSE);
- }
- LRESULT CClientDlg::OnNetwork(WPARAM wParam, LPARAM lParam)
- {
- SOCKET s = (SOCKET)wParam;
- WORD netEvent = WSAGETSELECTEVENT(lParam);
- WORD error = WSAGETSELECTERROR(lParam);
- if(error!=0){
- msg.Format("Error code: %d/n",error);
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(msg);
- if(error==WSAECONNREFUSED){
- msg.Format("Connection refused./n");
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(msg);
- closesocket(sock);
- WSACleanup();
- GetDlgItem(IDC_DISCONNECT)->EnableWindow(FALSE);
- GetDlgItem(IDC_SEND)->EnableWindow(FALSE);
- GetDlgItem(IDC_CHANGENAME)->EnableWindow(FALSE);
- GetDlgItem(IDC_CONNECT)->EnableWindow(TRUE);
- GetDlgItem(IDC_IP)->EnableWindow(TRUE);
- GetDlgItem(IDC_PORT)->EnableWindow(TRUE);
- }
- return -1;
- }
- switch(netEvent){
- case FD_CONNECT:
- OnConnect(s);
- break;
- case FD_READ:
- OnRead(s);
- break;
- case FD_CLOSE:
- OnCloseSocket(s);
- break;
- }
- return 0;
- }
- void CClientDlg::OnConnect(SOCKET s)
- {
- msg.Format("Connected to %s:%d/n",inet_ntoa(serverAddr.sin_addr),ntohs(serverAddr.sin_port));
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(msg);
- }
- void CClientDlg::OnRead(SOCKET s)
- {
- static char buf[4096];
- int bytes;
- bytes = recv(s, buf, sizeof(buf), 0);
- if(bytes==SOCKET_ERROR || bytes==0){
- msg.Format("Socket error %d/n",WSAGetLastError());
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(msg);
- closesocket(s);
- return;
- }
- buf[bytes] = '/0';
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(buf);
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel("/n");
- }
- void CClientDlg::OnCloseSocket(SOCKET s)
- {
- closesocket(s);
- msg = "Connection closed./n ";
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(msg);
- GetDlgItem(IDC_DISCONNECT)->EnableWindow(FALSE);
- GetDlgItem(IDC_SEND)->EnableWindow(FALSE);
- GetDlgItem(IDC_CHANGENAME)->EnableWindow(FALSE);
- GetDlgItem(IDC_CONNECT)->EnableWindow(TRUE);
- GetDlgItem(IDC_IP)->EnableWindow(TRUE);
- GetDlgItem(IDC_PORT)->EnableWindow(TRUE);
- WSACleanup();
- }
- void CClientDlg::OnBnClickedSend()
- {
- UpdateData(TRUE);
- int bytes;
- bytes = send(sock,(const char*)m_message,m_message.GetLength(),0);
- if(bytes==SOCKET_ERROR){
- int error = WSAGetLastError();
- if(error==WSAEWOULDBLOCK){
- msg = "Send failed for message: ";
- msg+=m_message;
- }else{
- msg.Format("Connection is down.");
- }
- m_allmsg.SetSel(32767,32767);
- m_allmsg.ReplaceSel(msg);
- }
- }
- void CClientDlg::OnBnClickedDisconnect()
- {
- shutdown(sock,SD_SEND);
- }
- void CClientDlg::OnClose()
- {
- //MessageBox("close");
- closesocket(sock);
- WSACleanup();
- CDialog::OnClose();
- }
- void CClientDlg::OnBnClickedQuit()
- {
- SendMessage(WM_CLOSE);
- }
- void CClientDlg::OnBnClickedChangeName()
- {
- UpdateData(TRUE);
- char buf[100];
- sprintf(buf,"name %s",m_nickname);
- if(send(sock,buf,strlen(buf),0)==SOCKET_ERROR){
- MessageBox("发送改名命令失败!");
- return;
- }
- }
原理请参考我的课件: http://www.oakcms/network
0 0
- 基于WSAAsyncSelect模型实现的聊天室图形客户端
- 基于WSAAsyncSelect模型实现的聊天室图形客户端
- 基于WSAAsyncSelect模型实现的聊天室图形客户端
- 基于WSAAsyncSelect模型实现的聊天室图形客户端
- WSAAsyncSelect模型 实现socket客户端接收数据的例子
- 基于WSAAsyncSelect实现的服务器
- 使用socket实现基于select模型的网络聊天室
- WSAAsyncselect 模型中,服务器与客户端消息的收发
- WSAAsyncSelect模型的使用
- Android聊天室客户端的实现
- WSAAsyncSelect模型Delphi简单实现
- WSAAsyncSelect模型Delphi简单实现
- WSAAsyncSelect模型Delphi简单实现
- 基于netty 的android Socket 聊天室客户端
- 基于UDP的简易聊天室(客户端)
- 基于Linux的聊天室(客户端)初成版
- 基于Linux C 用socket和线程 实现的简易聊天室之客户端
- 基于IE浏览器的图形聊天室(类可乐8)
- Android学习笔记之一android布局--Android fill_parent、wrap_content和match_parent的区别
- 斜率优化题目(持续更新)
- yii 2.0 写入日志
- 自动化在Android应用UI适配测试中的应用
- shucursor标签的使用
- 基于WSAAsyncSelect模型实现的聊天室图形客户端
- 输入法自动化性能测试
- C# 模拟 Http 请求
- 需求测不完怎么办?
- “钩子”技术在白盒测试中的应用
- 需求了解要做什么?
- 搜狗输入法BUG分析(一):根据bug趋势确定代码稳定性
- 搜狗测试管理两大“女神”
- 搜狗浏览器单元测试流程规划