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 - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
