C++打造局域网聊天室第十二课: 客户端和服务端的切换

ops/2024/12/23 14:03:35/

文章目录

  • 前言
  • 一、补充说明
  • 二、客户端和服务端身份状态的切换
  • 三、点击关闭窗口按钮
  • 总结


前言

C++打造局域网聊天室第十二课: 客户端和服务端的切换


一、补充说明

在C++打造局域网聊天室第十一课: 程序关闭及线程的结束中描述的服务端线程的关闭和结束是存在bug的,这里进行补充说明。
按照上述链接的程序,在关闭服务端时,会出现如下bug:
在这里插入图片描述
在这里插入图片描述
即在第一次点击服务端停止按钮后,客户端不会出现服务端断开提示,在第二次点击服务端停止按钮后,客户端才出现提示。经过博主Debug发现造成这种现象的原因是:在点击服务端停止按钮后,由于服务端对应的bShutDown为1,Server.cpp中的程序会跳出死循环,但是之前对于Server.cpp中的程序只实现了关闭监听线程,而与客户端通信的线程没有调用closesocket()关闭。所以WaitForMultipleObjects()会超时,调用TerminateThread()进行强制与客户端连接线程的结束,由于第一次点击服务端停止按钮后WaitForMultipleObjects()超时,客户端的SOCKET_Select(m_ClientItem.m_Socket, 100, TRUE)函数不会返回1,所以客户端不会出现服务端断开提示。而在第二次点击服务端停止按钮时,服务端的监听线程和与客户端的通信线程已经全都关闭,WaitForMultipleObjects()不会超时,所以客户端会正常提示。解决办法为在Server.cpp的如图位置加入框中代码:
在这里插入图片描述
此时,在第一次点击服务端停止按钮后,不光对服务端监听线程进行了关闭,也对与客户端通信的线程进行了关闭,WaitForMultipleObjects()不会超时,客户端会正常提示:
在这里插入图片描述

二、客户端和服务端身份状态的切换

如果本程序为客户端,点击服务端选项后,要提醒用户,并停止客户端。添加后,点击服务器选项和客户端选项的MFC消息映射机制函数变为:

void CchartroomDlg::OnBnClickedRadio2()//点击服务器选项的MFC消息映射机制
{// TODO: 在此添加控件通知处理程序代码INT iRet = -1;// 添加客户端切换服务端程序if (m_bIsServer == 0) // 如果当前程序为服务端{iRet = MessageBox(_T("您正在聊天中,要退出吗?"), 0, MB_OKCANCEL);if (iRet == IDOK) // 如果用户真想关闭{StopClient(); // 停止服务端}else{CheckRadioButton(IDC_RADIO1, IDC_RADIO2, IDC_RADIO1); // 置为客户端}}if (iRet == IDOK || m_bIsServer == -1){EnableWindow(IDC_BUTTON2, 0);// 利用自己定义的函数禁用客户器端的停止按钮EnableWindow(IDC_IPADDRESS1, 0);// 利用自己定义的函数禁用服务器IPEnableWindow(IDC_EDIT6, 0);// 利用自己定义的函数禁用服务器端口EnableWindow(IDC_BUTTON1, 0);// 利用自己定义的函数禁用连接服务器EnableWindow(IDC_BUTTON2, 0);// 利用自己定义的函数禁用客户端的停止按钮EnableWindow(IDC_EDIT7, 1);// 利用自己定义的函数允许本地监听端口EnableWindow(IDC_BUTTON3, 1);// 利用自己定义的函数允许开启服务器EnableWindow(IDC_BUTTON4, 1);// 利用自己定义的函数允许服务器端停止按钮}}void CchartroomDlg::OnBnClickedRadio1()//点击客户端选项的MFC消息映射机制
{// TODO: 在此添加控件通知处理程序代码INT iRet = -1;// 添加服务端切换客户端程序if (m_bIsServer == 1) // 如果当前程序为服务端{iRet = MessageBox(_T("您是聊天室的服务端,如果您退出,所有客户端都会掉线"), 0, MB_OKCANCEL);if (iRet == IDOK) // 如果用户真想关闭{StopServer(); // 停止服务端}else{CheckRadioButton(IDC_RADIO1, IDC_RADIO2, IDC_RADIO2); // 置为服务端}}if (iRet == IDOK || m_bIsServer == -1){EnableWindow(IDC_BUTTON2, 1);// 利用自己定义的函数允许客户器端的停止按钮EnableWindow(IDC_IPADDRESS1, 1);// 利用自己定义的函数允许服务器IPEnableWindow(IDC_EDIT6, 1);// 利用自己定义的函数允许服务器端口EnableWindow(IDC_BUTTON1, 1);// 利用自己定义的函数允许连接服务器EnableWindow(IDC_BUTTON2, 1);// 利用自己定义的函数允许客户端的停止按钮EnableWindow(IDC_EDIT7, 0);// 利用自己定义的函数禁用本地监听端口EnableWindow(IDC_BUTTON3, 0);// 利用自己定义的函数禁用开启服务器EnableWindow(IDC_BUTTON4, 0);// 利用自己定义的函数禁用服务器端停止按钮}
}

三、点击关闭窗口按钮

在这里插入图片描述
点击关闭后,不光要关闭窗口,还要终止服务端和客户端对应的线程

void CchartroomDlg::OnBnClickedButton6() // 点击关闭窗口按钮的MFC消息映射机制
{// TODO: 在此添加控件通知处理程序代码if (m_bIsServer == 1) // 如果为服务端{StopServer();}else if (m_bIsServer == 0) // 如果为客户端{StopClient();}OnCancel(); // 关闭窗口
}

总结

C++打造局域网聊天室第十二课: 客户端和服务端的切换


http://www.ppmy.cn/ops/144316.html

相关文章

了解 SpringMVC 请求流程

文章目录 1. Spring 基础 - SpringMVC 请求流程1.1 引入1.2 什么是 MVC1.3 什么是 Spring MVC1.4 请求流程核心架构的具体流程步骤补充 1.5 案例**Maven 包引入****业务代码的编写**DaoServiceControllerwebapp 下的 web.xmlspringmvc.xmlJSP 视图 2. Spring 进阶 - Dispatcher…

C语言:排序

1. 插入排序 (Insertion Sort) 插入排序是一种简单直观的排序算法,它的工作原理类似于整理扑克牌。它的基本思想是将数组分为已排序部分和未排序部分,每次从未排序部分取出一个元素,插入到已排序部分的合适位置。 步骤: 从数组…

基于知识图谱的医疗问答系统(dockerfile+docker-compose)

文章目录 一、搭建 Neo4j 图数据库1、方式选择2、Dockerfiledocker-compose部署neo4j容器2.1、更新 yum 镜像源2.2、安装 docker-ce 社区版2.3、配置镜像加速2.4、安装 Docker Compose2.4.1、下载 Docker Compose 二进制包2.4.2、设置可执行权限2.4.3、查看版本 2.5、创建目录结…

国产 HighGo 数据库企业版安装与配置指南

国产 HighGo 数据库企业版安装与配置指南 1. 下载安装包 访问 HighGo 官方网站(https://www.highgo.com/),选择并下载企业版安装包。 2. 上传安装包到服务器 将下载的安装包上传至服务器,并执行以下命令: [rootmas…

最大似然检测在通信解调中的应用

最大似然检测(Maximum Likelihood Detection,MLD),也称为最大似然序列估计(Maximum Likelihood Sequence Estimation,MLSE),是一种在通信系统中广泛应用的解调方法。其核心思想是在给…

使用NodeJs 实现图片转PPT

序言 帮朋友下载网络资源。最后转化为PPT 网页是这样的 下载图片 需要使用nodejs来下载图片 安装需要的库 npm install axios执行下面的JS const fs require(fs); const path require(path); const axios require(axios); const { URL } require(url); const readlin…

从零开始学前端之HTML(三)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 HTML CSS 内联样式内部样式表外部样式表 HTML图像HTML 表格HTML列表HTML区块HTML表单HTML框架 HTML CSS 内联样式- 在HTML元素中使用"style" 属性 内部…

驾驶证识别API-JavaScript驾驶证ocr接口集成-场景解析

随着数字化转型的加速和人工智能技术的进步,驾驶证识别技术正逐渐成为众多行业优化服务流程、提升用户体验的关键工具,它不仅仅是一个简单的信息提取过程,更体现了现代信息技术与传统交通管理融合的新趋势。 通过集成驾驶证识别技术&#xff…