基于WSAAsyncSelect模型实现的聊天室图形客户端
对应的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;
- }
- }
基于WSAAsyncSelect模型实现的聊天室图形客户端
基于WSAAsyncSelect模型实现的聊天室图形客户端相关推荐
- 使用socket实现基于select模型的网络聊天室
假期闲来无事,便写了个小小的网络聊天室程序.以前一直都是写MFC的有界面的程序,时间长了,便失去了兴趣,感觉有些东西经过MFC的封装,反而失去了意义,让人学不到东西,所以,丢开MFC那层的东西,直接使 ...
- Linux下基于socket和多线程的聊天室小程序
转载:http://blog.csdn.net/robot__man/article/details/52460733 要求:基于TCP编写,一个聊天室最多100人. 客户端: 1.用户需要登录, ...
- 基于TCP的网络实时聊天室(socket通信案例)
开门见山 一.数据结构Map 二.保证线程安全 三.群聊核心方法 四.聊天室具体设计 0.用户登录服务器 1.查看当前上线用户 2.群聊 3.私信 4.退出当前聊天状态 5.离线 6.查看帮助 五.聊 ...
- 基于UDP/IP协议的聊天室
基于TCP/IP通信协议的聊天室 概述: 基于TCP/IP通信协议的聊天室是通过服务端/客户端的模式进行的,必须是服务端开启之后,客户端通过获取服务端的ip和端口号并连接之后才能进行信息的共享,具体的 ...
- 可以发送图片文件的php聊天室,基于 Swoole 开发实时在线聊天室(十四):发送图片消息...
基于 Swoole 开发实时在线聊天室(十四):发送图片消息 由 学院君 创建于1年前, 最后更新于 1年前 版本号 #1 2055 views 0 likes 0 collects 上篇教程我们演示 ...
- 基于SSM的Web网页聊天室系统设计与实现 毕业论文+项目源码及数据库文件、
下载地址:https://download.csdn.net/download/ouyangxiaobai123/22679732 项目介绍: 基于SSM的Web网页聊天室系统设计与实现 毕业论文+项 ...
- 视频教程-基于Java的WebSocket的聊天室-Java
基于Java的WebSocket的聊天室 多年 Java 企业级应用开发工作经验,曾参与中国人寿.华夏人寿.泰康人寿.信达财险等保险行业内部业务管理系统以及线上在线产品的开发:参与中国人民银行.清华大 ...
- 网络编程-基于MFC的仿QQ聊天室-2020
基于MFC的仿QQ聊天室(2020) 有幸学习过网络编程的一些知识,出于对编程的热爱,把曾经的一次简单实践编程作业进行了自定义的完成. 编程所需: 编程工具为VS 2010,需要掌握MFC的基本操作以 ...
- Linux下后台服务器开发_基于多线程的一对一QQ聊天室
废话不多说直接上干货 1.目标 在实现回声服务器和客户端后 ,基于多线程设计一对一的聊天室 2.功能 在本机上实现客户端与服务器的实时聊天测试 以达到练习强化socket通信/多线程技术的目的 3.测 ...
最新文章
- 高精地图与自动驾驶(上)
- 用C#调用Windows API向指定窗口发送按键消息
- c语言中div函数,C 库函数
- 二叉树初始化_Java实现二叉树
- ExtJs 3.1 XmlTreeLoader Example Error
- Android 显示全文折叠控件
- 在google play开放平台上closed texting如何删除_“爷青回”!如何抢先体验《英雄联盟》手游?这份攻略送给你...
- JS面向对象程序设计(OOP:Object Oriented Programming)
- batchsize一定是2的幂_学习率和batchsize如何影响模型的性能?
- db2 查看表结构_数据库结构文档的生成利器
- 【PAT甲】1001 A+B Format (20分) 格式化输出
- np.roll()的理解和用法
- 工作日志之MTK刷机
- matlab中函数迭代法,Matlab 数值计算----斯特芬森加速迭代法
- js获取USB扫码枪数据
- 微信小程序重新发起请求加载页面
- 对java导出PDF进行图片,(图片/文字)水印,页眉页脚的添加
- Linux系统用C语言设计酒店管理系统
- 一起学英语-英语名词,代词,动词辨析,混合词序,原级比较,形容词副词比较,多音节形容词,接词连词冠词,动词时态
- [RK3288][Android6.0] USB OTG模式及切换
热门文章
- Filter_细节_web.xml配置方式
- eureka架构图原理
- JavaScript中替换字符串中的所有小数点
- 200730学习日报6字符串
- 洛谷 P1983 车站分级
- Spark学习之Spark调优与调试(7)
- 安装在谷歌axure小工具
- 有没有通过代码退出程序的方法--官方解答
- row_number() over (partition by....order by...)用法 分组排序
- No symbols have been loaded for this document