MFC-TCP网络编程服务端-Socket
目录
1、通过Socket建立服务端:
2、UI设计:
3、代码的实现:
(1)、CListenSocket类
(2)、CConnectSocket类
(3)、CTcpServerDlg类
1、通过Socket建立服务端:
(1)、创建一个Socket对象并绑定一个端口:CListenSocket 监听Socket
(2)、通过Listen()函数,监听来自客户端的连接请求
(3)、连接请求到来之后,建立一个通信用的Socket,CConnectSocket,并且加入数组中
(4)、使用Send()、Receive()函数,接收客户端发送的数据,并遍历数组,一次转发消息
2、UI设计:
3、代码的实现:
(1)、CListenSocket类
CListenSocket的目的是等待客户端的连接请求,继承Socket类,重写Socket的OnAccept函数,创建Socket对象,连接的初始化和等待客户端连接。
CListenSocket.h中
CListenSocket(CTcpServerDlg * pdlg);//传递对话框的指针
~CListenSocket();
virtual void OnAccept(int nErrorCode);//重写父类
CTcpServerDlg *m_pMainDlg;//接收传递的对话框指针
CListenSocket.cpp中
CListenSocket::CListenSocket(CTcpServerDlg * pdlg)
{
m_pMainDlg = pdlg; //初始化接收的对话框指针
}
void CListenSocket::OnAccept(int nErrorCode)
{
// TODO: 在此添加专用代码和/或调用基类CSocket::OnAccept(nErrorCode);
m_pMainDlg->ProcessPendingAccept();//对于连接函数的处理放在对话框函数中处理
}
(2)、CConnectSocket类
CConnectSocket的目的是通讯用的Socket,继承Socket类,重写Socket的OnReceive函数,数据的接收和处理以及数据的解析。
CConnectSocket.h中
CConnectSocket(CTcpServerDlg *pdlg);
~CConnectSocket();
virtual void OnReceive(int nErrorCode);
CTcpServerDlg *m_pMainDlg;
CConnectSocket.cpp中
CConnectSocket::CConnectSocket(CTcpServerDlg *pdlg)
{
m_pMainDlg = pdlg;
}
void CConnectSocket::OnReceive(int nErrorCode)
{
// TODO: 在此添加专用代码和/或调用基类CSocket::OnReceive(nErrorCode);
m_pMainDlg->ProcessPendingRead(this);//接收消息必须要传递指针进去,调用接收函数
}
(3)、CTcpServerDlg类
1)、声明服务端用于监听的socket
//服务端声明的用于监听的socket
CListenSocket *m_pListenSocket;
2)、声明一个CArray的对象,里面存放的CConectSocket指针
CArray<CConnectSocket*, CConnectSocket*&>m_ConnectSocketList;
//m_ConnectSocketList是CArray的一个对象,里面放着CConnectSocket的指针,并且可以对里面的数据进行访问和修改。
// CConnectSocket*&当数组元素被传递给函数时,使用引用方式传递元素,可以有效避免不必要的拷贝和内存开销。
3)、定义一个结构体,保存客户端的IP和Port
struct ClientAddr
{
CString strIp;
UINT uiPort;
};
4)、框架类的入口函数初始化监听Socket和端口号
m_pListenSocket = new CListenSocket(this);
//m_pListenSocket用来监听服务器的连接所以要分配内存
m_pListenSocket->Create(8080);
//初始化端口号
if (!m_pListenSocket->Listen())
{
MessageBox(L"监听失败!");
return FALSE;
}
5)、实现ProcessPendingAccept()函数
主要实现监听服务器的连接,监听到了就加到列表中
CConnectSocket *pConnectSocket = new CConnectSocket(this);
if (m_pListenSocket->Accept(*pConnectSocket))
{
m_ConnectSocketList.Add(pConnectSocket);
}
else {
delete pConnectSocket;
}
6)、实现ProcessPendingRead()函数
数据的接收,并且存放在buff中
TCHAR buff[4096];//存放接收到的数据
//接收数据
int nRead = connectSocket->Receive(buff, 4096);
if (nRead == SOCKET_ERROR)
{
return;
}buff[nRead] = L'\0';//接收到的数据末尾加上结束符
CString strTemp(buff);//格式化buff
把连接到的客户端IP和Port存放在结构体中
ClientAddr clientAddr;//用来存放客户端的IP和Port
//获取连接上来的客户端的IP和端口
connectSocket->GetPeerName(clientAddr.strIp, clientAddr.uiPort);
解析数据:加入房间enter
int i = 0;
//解析数据
if (strTemp.CompareNoCase(L"enter") == 0)
{
//通知其他客户端有人进入房间
CString strEnterMsg;
strEnterMsg.Format(L"系统消息:%s(%d)进入了房间", clientAddr.strIp, clientAddr.uiPort);
for ( i;i<m_ConnectSocketList.GetSize();i++)
{//遍历每一个客户端,并且发送消息给每个客户端。
CConnectSocket *& tempClient = m_ConnectSocketList.ElementAt(i);
tempClient->Send(strEnterMsg, strEnterMsg.GetLength() + 100);
}
显示到界面
//更新界面
SetDlgItemInt(IDC_EDIT_NUMBER, m_ConnectSocketList.GetSize());//显示当前客户端人数CString ALmSG;
GetDlgItemText(IDC_EDIT_MESSAGE, ALmSG);//EDIT上显示的之前的消息
SetDlgItemText(IDC_EDIT_MESSAGE, ALmSG + L"\r\n" + strEnterMsg);
//显示的现在的消息加上之前的消息
解析数据:离开房间leave
//从列表中移除
for (i;i<m_ConnectSocketList.GetSize();i++)
{
CConnectSocket *&temClient = m_ConnectSocketList.ElementAt(i);
ClientAddr temClientAddr;
temClient->GetPeerName(temClientAddr.strIp, temClientAddr.uiPort);
if (temClientAddr.uiPort == clientAddr.uiPort && temClientAddr.strIp.Compare(clientAddr.strIp) == 0)
{//当前移除的IP和Port如果和加入的时候存放在结构体的一样直接跳出循环删除
break;
}
if (i<m_ConnectSocketList.GetSize())
{
m_ConnectSocketList.RemoveAt(i);
}
发送给每一个客户端消息
//通知所有人
CString strleaveMsg;
strleaveMsg.Format(L"系统消息:%s(%d)进入了房间", clientAddr.strIp, clientAddr.uiPort);
for (i; i < m_ConnectSocketList.GetSize(); i++)
{
CConnectSocket *& tempClient = m_ConnectSocketList.ElementAt(i);
tempClient->Send(strleaveMsg, strleaveMsg.GetLength() + 100);
}
更新界面
//更新界面
SetDlgItemInt(IDC_EDIT_NUMBER, m_ConnectSocketList.GetSize());CString ALmSG;
GetDlgItemText(IDC_EDIT_MESSAGE, ALmSG);
SetDlgItemText(IDC_EDIT_MESSAGE, ALmSG + L"\r\n" + strleaveMsg);
发送的是普通消息
//遍历每一个客户端发出,然后更新界面即可
CString strMsg;
strMsg.Format(L"%s(%d):%s", clientAddr.strIp, clientAddr.uiPort,strTemp);
for (i; i < m_ConnectSocketList.GetSize(); i++)
{
CConnectSocket *& tempClient = m_ConnectSocketList.ElementAt(i);
tempClient->Send(strMsg, strMsg.GetLength() + 100);
}
//更新界面
SetDlgItemInt(IDC_EDIT_NUMBER, m_ConnectSocketList.GetSize());CString ALmSG;
GetDlgItemText(IDC_EDIT_MESSAGE, ALmSG);
SetDlgItemText(IDC_EDIT_MESSAGE, ALmSG + L"\r\n" + strMsg);
相关文章:

MFC-TCP网络编程服务端-Socket
目录 1、通过Socket建立服务端: 2、UI设计: 3、代码的实现: (1)、CListenSocket类 (2)、CConnectSocket类 (3)、CTcpServerDlg类 1、通过Socket建立服务端ÿ…...
ChatGPT辅助下的小组学习
1 网上分享会-主题 1.9曾子曰:“慎终追远,民德归厚矣。” Master Zeng said:“Be circumspect in funerary services and continue sacrifices to the distant ancestors, and the virtue (de 德) of the common people will thrive.” 2 过程记录 听…...
Linux相关命令
切换root用户:sudo su 串口功能测试:cutecom 某某驱动查询:nvidia-smi #xxx-smi查询某某驱动 在线安装某某程序:apt install xxx 设置文件权限chmod 常用:chmod 777 sudo chmod 600 (只有所有者…...

详解卷积神经网络结构
前言 卷积神经网络是以卷积层为主的深度网路结构,网络结构包括有卷积层、激活层、BN层、池化层、FC层、损失层等。卷积操作是对图像和滤波矩阵做内积(元素相乘再求和)的操作。 1. 卷积层 常见的卷积操作如下: 卷积操作解释图解…...
java读取pdf数据
目录 读取方式有两种: 方式一: 方式一所需要的maven依赖如下: 方式一读取的Java代码如下:<...
arcmap / arcgis 安装教程
ArcGIS 10.8 for Desktop 完整安装教程(含win7/8/10 32/64位下载地址亲测可用汉化) | 麻辣GIS (malagis.com) 关于GIS语言汉化包(中文)安装失败的解决办法_arcgis中文语言包_miumiuniya的博客-CSDN博客 检查安装路径:…...
CMake中的变量: 改变构建行为的变量
文章目录 变量名称描述BUILD_SHARED_LIBS全局标志,用于在启用时使add_library()创建共享库。 如果存在并且为true,则这将导致所有库被构建为共享库,除非该库被明确添加为静态库。这个变量通常作为option()添加到项目中,这样项目的…...

台式电脑怎么无损备份迁移系统到新硬盘(使用傲梅,免费的就可以)
文章目录 前言一、想要将源硬盘上的系统原封不动地迁移到新硬盘上二、准备工作2.具体步骤 总结 前言 半路接手公司一台台式电脑,C盘(120g)爆红,仅剩几个G,优化了几次,无果后。准备换一个大一点的增到500g。…...

【紫光同创国产FPGA教程】【PGC1/2KG第七章】7.数字钟实验例程
本原创教程由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处 适用于板卡型号: 紫光同创PGC1/2KG开发平台(盘古1K/2K) 一:盘古1K/2K开发板(紫光同创PGC…...
【星海随笔】git的使用
1.在终端,检查git是否安装 git --version 2.没有安装的话去,官网,下载git 3.一直点下一步即可 4.安装后在终端检查git是否安装好 5.设置用户名和邮件地址(最好和GitHub的用户名/邮箱保持一致) git config --global user.name “自己的用户名”…...
安卓常见设计模式------装饰器模式(Kotlin版)
1. W1 是什么,什么是装饰器模式? 思想:动态地给对象添加额外的功能,通过将对象包装在一个装饰器类中,使装饰器类在不改变原始对象结构的情况下,扩展其功能。 2. W2 为什么,为什么需要使用装饰…...

将网站上的点击作为转化操作进行跟踪-官方指导文档
您可以使用转化跟踪功能,在用户点击您网站上的某个按钮或链接时进行跟踪。例如,您可以在用户点击“立即购买”按钮或点击您移动网站上的电话号码时进行跟踪。 本文介绍如何添加和修改转化跟踪代码,以便跟踪客户在您网站上的点击操作。如果希…...
Go相关命令说明
目录 Go相关命令说明go mod tidy :清理未使用依赖项,并更新模块文件主要功能好处 go clean -modcache :清除模块缓存go clean -testcache :清除测试缓存go test -v ./client :测试当前目录下client目录中的所有测试函数…...

3D全景技术,为我们打开全新宣传领域
随着科技的发展,3D全景技术正在融入我们的生活,这种全新视觉体验方式为我们打开了一扇全新的宣传领域,可以让我们多方位、多视角地探索各个行业,无论是对教育、商业、还是其他领域,都产生了深远的影响。 3D全景技术结合…...
【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割10(测试推理篇)
对于直接将裁剪的patch,一个个的放到训练好的模型中进行预测,这部分代码可以直接参考前面的训练部分就行了。其实说白了,就是验证部分。不使用dataloader的方法,也只需要修改少部分代码即可。 但是,这种方法是不end to end的。我们接下来要做的,就是将一个CT数组作为输入…...

PyCharm+Miniconda3安装配置教程
PyCharm是Python著名的Python集成开发环境(IDE) conda有Miniconda和Anaconda,前者应该是类似最小化版本,后者可能是功能更为强大的版本,我们这里安装Miniconda 按官方文档的说法conda相当于pip与virtualenv的结合&am…...

【慢SQL性能优化】 一条SQL的生命周期 | 京东物流技术团队
一、 一条简单SQL在MySQL执行过程 一张简单的图说明下,MySQL架构有哪些组件和组建间关系,接下来给大家用SQL语句分析 例如如下SQL语句 SELECT department_id FROM employee WHERE name Lucy AND age > 18 GROUP BY department_id其中name为索引&a…...

小程序day05
使用npm包 Vant Weapp 类似于前端boostrap和element ui那些的样式框架。 安装过程 注意:这里建议直接去看官网的安装过程。 vant-weapp版本最好也不要指定 在项目目录里面先输入npm init -y 初始化一个包管理配置文件: package.json 使用css变量定制vant主题样式࿰…...

Docker两个容器互相请求接口
BEGIN 环境:Docker-Windows-Hyperf 1. 过以下命令查看Docker中的所有网络 docker network ls这个命令会列出所有的Docker网络,包括其ID、名称、驱动以及作用范围 在 Docker 中,容器通过 Docker 网络进行相互通信;在 Docker 中有…...

UML与PlantUML简介
UML与PlantUML 1、UML与PlantUML概述2、PlantUML使用 1、UML与PlantUML概述 UML(Unified Modeling Language)是一种统一建模语言,为面向对象开发系统的产品进行说明、可视化、和编制文档的一种标准语言,独立于任何具体程序设计语言…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...