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);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/185454.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot + EasyUI Datebox和Datetimebox样例

使用EasyUI的Datebox和Datetimebox组件&#xff0c;并对其进行适当的改造&#xff0c;比如更改日期格式、设置默认值或者将当前时间设置为默认值。 一、运行结果 二、实现代码 1.代码框架 2.实现代码 SpringBootMainApplication.java: package com.xj.main;import org.spri…

μC/OS-II---内核:多任务与调度

目录 内核&#xff1a;多任务&#xff08;ucos_ii.h文件的函数&#xff09;Task创建Task创建&#xff08;扩展&#xff09;Task删除/请求删除Task改变Task优先级Task挂起和恢复Task信息获取Task调度器上锁和开锁 内核&#xff1a;调度&#xff08;oc_core.c文件的函数&#xff…

MySQL系列-win10安装MySQL

MySQL系列-win10安装MySQL 1. MySQL系列-win10安装MySQL1.1MySQL下载安装MySQL5.71.2MySQL下载再安装MySQL8.0 未完待续 1. MySQL系列-win10安装MySQL 1.1MySQL下载安装MySQL5.7 下载地址 https://www.mysql.com/downloads/ 进入后&#xff0c;下拉页面&#xff0c;最下面有社…

搜款网VVIC商品详情API接口

搜款网VVIC商品详情接口提供了全面的API接口&#xff0c;通过该接口&#xff0c;开发者可以使用商品ID等参数请求API&#xff0c;获取商品的详细信息&#xff0c;如商品标题、描述、价格、库存状态、销售量等。 要使用VVIC商品详情接口&#xff0c;您需要先注册开发者账号并申…

每天一点python——day65

#每天一点Python——65 #字符串的内容对齐操作类似于word中左对齐、右对齐、居中对齐如图 #例&#xff1a; s1hello,python print(s1.center(20,*))#设置宽度20&#xff0c;填充图是*s1有12个字符&#xff0c;这个字符串的宽度设置为20&#xff0c; 20-128 因为center是居中对齐…

【唠唠嵌入式】__嵌入式开发需要从0开始造轮子吗?

目录 前言 从0开始和套用模板的利弊 1. 从0开始的利弊 2. 套用模板的利弊 从0开始&#xff0c;还是套用模板&#xff1f; 1. 看项目赶不赶 2. 看项目用途 3. 看工程师水平 4. 看领导决策 5. 看公司决策 6. 看项目规划 实际工作 总结 (*&#xffe3;︶&#xffe3…

java数据结构--双端队列

一.概念 双端队列的意思是可以在头部和尾部添加和删除元素&#xff0c;更一般的单向链表队列比起来更加的灵活&#xff0c;下面我们用双向循环带哨兵链表和数组来分别实现 二.定义接口Dequeue /*** 双端队列*/ public interface Dequeue<E> {//队头添加元素boolean off…

QT QStackedWidget

QStackedWidget是一个特殊的布局容器&#xff0c;它可以管理多个页面&#xff0c;并且只能显示其中一个页面。这些页面是QWidget或其派生类的实例&#xff0c;并通过调用addWidget()函数添加到堆栈中。 例如&#xff1a; #include <QWidgets> #include <QStackedWid…

10.(vue3.x+vite)组件间通信方式之props与$emit

前端技术社区总目录(订阅之前请先查看该博客) 示例效果 父组件代码 <template><div><div>{{message }}</div><Child

Scala爬虫实战:采集网易云音乐热门歌单数据

导言 网易云音乐是一个备受欢迎的音乐平台&#xff0c;汇集了丰富的音乐资源和热门歌单。这些歌单涵盖了各种音乐风格和主题&#xff0c;为音乐爱好者提供了一个探索和分享音乐的平台。然而&#xff0c;有时我们可能需要从网易云音乐上获取歌单数据&#xff0c;以进行音乐推荐…

【Azure 架构师学习笔记】-Azure Storage Account(5)- Data Lake layers

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Storage Account】系列。 接上文 【Azure 架构师学习笔记】-Azure Storage Account&#xff08;4&#xff09;- ADF 读取Queue Storage 前言 不管在云还是非云环境中&#xff0c; 存储是IT 系统的其中一个核心组件。在…

远程运维用什么软件?可以保障更安全?

远程运维顾名思义就是通过远程的方式IT设备等运行、维护。远程运维适用场景包含因疫情居家办公&#xff0c;包含放假期间出现运维故障远程解决&#xff0c;包含项目太远需要远程操作等等。但远程运维过程存在一定风险&#xff0c;安全性无法保障&#xff0c;所以一定要选择靠谱…

【紫光同创国产FPGA教程】——PDS安装教程

本原创教程由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处 一&#xff1a;软件简介 PangoDesign Suite是紫光同创基于多年FPGA开发软件技术攻关与工程实践经验而研发的一款拥有国产自主知识产权的大规模FPGA开…

chinese-stable-diffusion中文场景文生图prompt测评集合

我在git上新建了一个仓库&#xff0c;主要是总结一波了chainese-stable-diffusion的模型算法&#xff0c;非常欢迎关注&#xff1a; GitHub - leeguandong/Awesome-Chinese-Stable-Diffusion: 中文文生图stable diffsion模型集合中文文生图stable diffsion模型集合. Contribute…

C语言:深入浅出qsort方法,编写自己的qsort完成冒泡排序

目录 什么是qsort&#xff1f; 函数原型 比较函数 compar 排序整型数组 排序结构体数组 根据成员字符排序 strcmp函数 根据成员整型排序 自定义qsort实现冒泡排序 qsort的实现原理 具体步骤 快速排序示例代码&#xff1a; 什么是qsort&#xff1f; qsort是 C …

[AndroidStudio]_[初级]_[修改虚拟设备镜像文件的存放位置]

场景 在使用Android Studio的虚拟设备运行App时&#xff0c;需要创建很大镜像文件。这些镜像文件一般都在系统盘&#xff0c;导致系统盘占用增大。怎么把这些镜像的存放路径设置在其他盘&#xff1f; 说明 虚拟设备的和它的镜像默认是放在用户目录\.android\avd位置。如果是在…

深入OpenCV Android应用开发

前言 OpenCV是Open Source Computer Vision library(开源的计算机视觉库)的缩写。它是使用最广泛的计算机视觉库。Opencv是计算机视觉领域常用的操作函数的集合&#xff0c;其自身由C/C编写而成&#xff0c;同时也提供了对Python、Java以及任意JVM语言的封装。考虑到大部分And…

统信UOS_麒麟KYLINOS创建网页桌面快捷方式

原文链接&#xff1a;统信UOS/麒麟KYLINOS创建网页桌面快捷方式 hello&#xff0c;大家好啊&#xff0c;今天给大家带来一篇使用命令行在统信UOS/麒麟KYLINOS创建网页桌面快捷方式的文章&#xff0c;主要用于构建云桌面模板及镜像模板的时候使用&#xff0c;欢迎大家浏览分享转…

数据库数据恢复—无备份,未开启binlog的MySQL误删除怎么恢复数据

数据库数据恢复环境&#xff1a; 一台本地windows sever操作系统服务器&#xff0c;服务器上部署mysql数据库单实例&#xff0c;引擎类型为innodb&#xff0c;表内数据存储所使用表空间类型为独立表空间。无数据库备份&#xff0c;未开启binlog。 数据库故障&分析&#xf…

05预测识别-依托YOLO V8进行训练模型的识别——对视频中的目标进行跟踪统计

上文中详细介绍了如何对视频进行抽帧,并对帧的图像进行目标识别。但在日常工作中,我们也会遇到需要对目标进行跟踪统计的情况,比如我们需要连续统计某一类目标有多少个的时候,如果单纯从帧中抽取图像的话,系统将无法判断是否为同一目标,从而造成目标数量统计的重复,导致…