Qt网络通信实战(聊天室小项目TCP实现)

2023-05-16

一、UDP与TCP的区别

用一个表格来显示这两者的区别

比较项TCPUDP
是否连接面向连接无连接
传输是否可靠可靠不可靠
流量控制提供不提供
工作方式全双工可以是全双工
应用场合大量数据少量数据
速度

 

我们这里采用TCP

//当有新的连接出现时就会调用此函数,和newConnection功能类似
void Server::incomingConnection(int socketDescriptor)
{

    TcpClientSocket *tcpclientsocket = new TcpClientSocket(this);//只要有新的连接就生成一个新的通信套接字
    //将新创建的通信套接字描述符指定为参数socketdescriptor
    tcpclientsocket->setSocketDescriptor(socketDescriptor);
    //将这个套接字加入客户端套接字列表中
    tcpclientsocketlist.append(tcpclientsocket);
    //接收到tcpclientsocket发送过来的更新界面的信号
    connect(tcpclientsocket, SIGNAL(updateserver(QString,int)), this, SLOT(slotupdateserver(QString,int)));
    connect(tcpclientsocket, SIGNAL(clientdisconnected(int)), this, SLOT(slotclientdisconnect(int)));
}

这个函数我就不多说了,注释我写的很清楚了

二、客户端程序,

在Qt中往往客户端比较简单,这里只要一个类即可,继承QTcpSocket

#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QWidget>
#include <QTcpSocket>
namespace Ui {
class TcpClient;
}

class TcpClient : public QWidget
{
    Q_OBJECT

public:
    explicit TcpClient(QWidget *parent = 0);
    ~TcpClient();

private slots:
    //用来处理连接成功的信号
    void slotconnectedsuccess();
    //接收服务器传过来的信息
    void slotreceive();
    //用来处理离开聊天室的信号
    void slotdisconnected();
    //发送按钮的槽函数
    void on_Send_clicked();
    //进入离开聊天室按钮
    void on_pushButtonEnter_clicked();

private:
    Ui::TcpClient *ui;
    //用来判断是否进入了聊天室
    bool status;

    int port;

    QHostAddress *serverIP;

    QString userName;

    QTcpSocket *tcpsocket;

};


#endif // TCPCLIENT_H
#include "tcpclient.h"
#include "ui_tcpclient.h"
#include <QHostAddress>
#include <QMessageBox>
#include <QDebug>


TcpClient::TcpClient(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TcpClient)
{
    ui->setupUi(this);
    //将进入聊天室的标志位置为false
    status = false;
    //端口为8888
    port = 5555;
    ui->Lineport->setText(QString::number(port));//界面中端口默认显示8888
    serverIP = new QHostAddress();
    //未进入聊天室内不能发送信息
    ui->Send->setEnabled(false);

}



TcpClient::~TcpClient()
{

    delete ui;

}

//用来处理连接成功的信号

void TcpClient::slotconnectedsuccess()
{
    //进入聊天室可以发送信息了
    ui->Send->setEnabled(true);
    //将进入聊天的按钮改为离开聊天室
    ui->pushButtonEnter->setText("离开聊天室");

    int length = 0;
    //将用户名发送给服务器
    QString msg= userName + " :Enter Chat Room";



    tcpsocket->write(msg.toUtf8().data());
}

void TcpClient::slotreceive()
{


    QByteArray array = tcpsocket->readAll();

    ui->textEdit->append(array);

}



void TcpClient::slotdisconnected()
{

    ui->Send->setEnabled(false);

    ui->pushButtonEnter->setText("进入聊天室");
}

void TcpClient::on_Send_clicked()
{
    if(ui->lineEditSend->text() == "")
    {
        return;
    }

    QString msg = userName + ":" + ui->lineEditSend->text();
    tcpsocket->write(msg.toUtf8().data());
    ui->lineEditSend->clear();
}

void TcpClient::on_pushButtonEnter_clicked()
{
    //首先判断这个用户是不是在聊天室中
        if(status == false)
        {
            //不在聊天室中就和服务器进行连接
            //从界面获取ip地址
            QString ip = ui->lineEditServerIp->text();
            //用这个函数判断IP地址是否可以被正确解析
            if(!serverIP->setAddress(ip))
            {
                //不能被正确解析就弹出一个警告窗口
                QMessageBox::warning(this, "错误", "IP地址不正确");
                return;
            }
            if(ui->lineEditUserName->text() == "")
            {
                //用户名不能为空,弹窗效果
                QMessageBox::warning(this, "错误", "用户名不能为空");
                return;
            }
            //从界面获取用户名
            userName = ui->lineEditUserName->text();
            //创建一个通信套接字,用来和服务器进行通信
            tcpsocket = new QTcpSocket(this);
             //和服务器进行连接
            tcpsocket->connectToHost(*serverIP, port);
            //和服务器连接成功能会触发connected信号
            connect(tcpsocket, SIGNAL(connected()), this, SLOT(slotconnectedsuccess()));
            //接收到服务器的信息就会触发readyRead信号
            connect(tcpsocket, SIGNAL(readyRead()), this, SLOT(slotreceive()));
              //将进入聊天室的标志位置为true;
            status = true;
        }
        else//已经进入了聊天室
        {
           int length = 0;
            QString msg = userName + ":Leave Chat Room";

            //离开之前给服务器发送离开信息
            tcpsocket->write(msg.toUtf8().data());
            tcpsocket->disconnectFromHost();
            status = false;
            //离开聊天室就会触发disconnected信号
            connect(tcpsocket, SIGNAL(disconnected()), this, SLOT(slotdisconnected()));
        }
}
#include <QtGui/QApplication>
#include "tcpclient.h"
#include <QTextCodec>

int main(int argc, char *argv[])
{
    //让中文字符不乱的固定套路
    QTextCodec* code = QTextCodec::codecForName("ut    f-8");
    QTextCodec::setCodecForTr(code);
    QTextCodec::setCodecForLocale(code);
    QTextCodec::setCodecForCStrings(code);
    QApplication a(argc, argv);
    TcpClient w;
    w.show();
    
    return a.exec();
}

这里说明一下,网上很多例子会把qt中生成的代码贴出来,只要自己创建就好了,没必要贴出来,主函数贴出来是是因为给出了解决中文字符乱码的小套路,大家可以学习一下。

三、服务端程序

服务端分为三个类,我注释写的挺详细了,看不懂评论解答

#ifndef TCPCLIENTSOCKET_H
#define TCPCLIENTSOCKET_H

#include <QTcpSocket>
//此类为一个继承了Qtcpsocket的类,为多客户端服务
class TcpClientSocket : public QTcpSocket
{
    Q_OBJECT
public:
    explicit TcpClientSocket(QObject *parent = 0);

signals:
    void updateserver(QString, int);//用来告诉tcpserver需要跟新界面的显示

    void clientdisconnected(int); //告诉server有客户端断开连接
    
protected slots:

    void receivedata();//处理readyRead信号读取数据

    void slotclientdisconnected();//客户端断开连接触发disconnected信号,这个槽函数用来处理这个信号

    
};

#endif // TCPCLIENTSOCKET_H
#include "tcpclientsocket.h"
#include <QDebug>

TcpClientSocket::TcpClientSocket(QObject *parent)
{

    //客户端发送数据过来就会触发readyRead信号
    connect(this, SIGNAL(readyRead()), this, SLOT(receivedata()));
    connect(this, SIGNAL(disconnected()), this, SLOT(slotclientdisconnected()));
}


void TcpClientSocket::receivedata()
{


    int length = 10;
    //读取客户端发送的信息并且发送信号给server端
    QByteArray array = readAll();
    QString msg = array;
    emit updateserver(msg,length);

}



void TcpClientSocket::slotclientdisconnected()
{
    emit clientdisconnected(this->socketDescriptor());
}
#ifndef SERVER_H
#define SERVER_H

#include <QTcpServer>
#include <QList>
#include <QObject>
#include "tcpclientsocket.h"

class Server : public QTcpServer
{
    Q_OBJECT
public:
    Server(QObject *parent = 0,int port=0);
    
    QList<TcpClientSocket*> tcpclientsocketlist;

protected:

    void incomingConnection(int socketDescriptor);//只要出现一个新的连接,就会自动调用这个函数

protected slots:

    void slotupdateserver(QString, int);//用来处理tcpclient发过来的信号

    void slotclientdisconnect(int);



signals:

    void updateserver(QString, int);//发送信号给界面,让界面更新信息
    
};

#endif // SERVER_H
#include "server.h"
#include <QHostAddress>
#include <QDebug>


Server::Server(QObject *parent, int port):QTcpServer(parent)
{
    listen(QHostAddress::Any, port); //监听

}
//当有新的连接出现时就会调用此函数,和newConnection功能类似
void Server::incomingConnection(int socketDescriptor)
{

    TcpClientSocket *tcpclientsocket = new TcpClientSocket(this);//只要有新的连接就生成一个新的通信套接字
    //将新创建的通信套接字描述符指定为参数socketdescriptor
    tcpclientsocket->setSocketDescriptor(socketDescriptor);
    //将这个套接字加入客户端套接字列表中
    tcpclientsocketlist.append(tcpclientsocket);
    //接收到tcpclientsocket发送过来的更新界面的信号
    connect(tcpclientsocket, SIGNAL(updateserver(QString,int)), this, SLOT(slotupdateserver(QString,int)));
    connect(tcpclientsocket, SIGNAL(clientdisconnected(int)), this, SLOT(slotclientdisconnect(int)));
}

void Server::slotupdateserver(QString msg, int length)
{
    //将这个信号发送给界面
    emit updateserver(msg, length);
    //将收到的信息发送给每个客户端,从套接字列表中找到需要接收的套接字
    for(int i = 0; i < tcpclientsocketlist.count(); i++)

    {

        QTcpSocket *item = tcpclientsocketlist.at(i);

        item->write(msg.toUtf8().data());
    }
}

void Server::slotclientdisconnect(int descriptor)
{
    for(int i = 0; i < tcpclientsocketlist.count(); i++)
    {
        QTcpSocket *item = tcpclientsocketlist.at(i);


        if(item->socketDescriptor() == descriptor)
        {
            //如果有客户端断开连接, 就将列表中的套接字删除
            tcpclientsocketlist.removeAt(i);
            return;
        }
    }
    return;
}

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QWidget>
#include"server.h"
#include <QString>

namespace Ui {
class Tcpserver;
}

class Tcpserver : public QWidget
{
    Q_OBJECT
    
public:
    explicit Tcpserver(QWidget *parent = 0);
    ~Tcpserver();
    
private:
    Ui::Tcpserver *ui;
    int port;
    Server* server;
public slots:
    void slotupdateserver(QString, int);//接收到server发过来的信号就更新界面的信息
private slots:
    void on_createbutoon_clicked();
};

#endif // TCPSERVER_H
#include "tcpserver.h"
#include "ui_tcpserver.h"
#include <QString>
#include <QDebug>

Tcpserver::Tcpserver(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Tcpserver)
{
    ui->setupUi(this);
    port=5555;
    ui->portline->setText(QString::number(port));
    server  = new Server(this, port);
    connect(server, SIGNAL(updateserver(QString, int)), this, SLOT(slotupdateserver(QString, int)));
   // ui->pushButtonCreateChattingRoom->setEnabled(false);
}

Tcpserver::~Tcpserver()
{
    delete ui;
}
void Tcpserver::slotupdateserver(QString msg, int length)

{
   

    ui->textEdit->append(msg);

}

void Tcpserver::on_createbutoon_clicked()
{
    server  = new Server(this, port);

    connect(server, SIGNAL(updateserver(QString,int)) ,this, SLOT(slotupdateserver(QString,int)));

    ui->createbutoon->setEnabled(false);
}
#include <QtGui/QApplication>
#include "tcpserver.h"
#include <QTextCodec>

int main(int argc, char *argv[])
{

    QTextCodec* code = QTextCodec::codecForName("ut    f-8");
    QTextCodec::setCodecForTr(code);
    QTextCodec::setCodecForLocale(code);
    QTextCodec::setCodecForCStrings(code);
    QApplication a(argc, argv);
    Tcpserver w;
    w.show();
    
    return a.exec();
}

这里主要用到很多的信号和槽函数,一层套着一层,从最上面看到下面就好了。有些只是控件名,在Qt中统一一下即可。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt网络通信实战(聊天室小项目TCP实现) 的相关文章

  • C语言指针详解(1)

    指针详解 之前我说过一篇关于指针在C语言中的基本使用 xff0c 这次我再来细讲一下指针的其他内容 目录 一 指针详解 1 指针定义 2 指针类型 3 野指针 4 如何规避野指针 xff1f 1 指针定义 指针理解的2个要点 xff1a 1
  • C语言结构体详解 (2) 结构体内存对齐,默认对齐数

    前言 上次 xff0c 我讲到了关于结构体的基本使用 xff0c 大家若感兴趣的话看一看我之前写的一篇结构体博客 xff0c 里面记载了我对于结构体的创建 初始化 嵌套结构体 结构体的访问访问方式和结构体传参方式等知识的见解 xff0c C
  • C语言——十进制转换十六进制

    请编写程序 xff0c 输入十进制数 xff0c 输出对应的十六进制数 输入格式 十进制非负整数 输出格式 对应的十六进制非负整数 要求 xff1a 十六进制数中的字母均为大写形式 输入样哩 5050 输出样例 13BA 代码输入 xff1
  • 如何编写头文件及使用Makefile

    头文件中应该写什么 xff1a 头文件可能会被任意源文件包含 xff0c 意味着头文件中的内容可能会在多个目标文件中存在 xff0c 要保证合并时不要冲突 重点 xff1a 头文件只编写声明语句 xff0c 不能有定义语句 全局变量声明 函
  • 剖析Linux内存中的/proc/meminfo参数

    PROC MEMINFO之谜 proc meminfo是了解Linux系统内存使用状况的主要接口 xff0c 我们最常用的 free vmstat 等命令就是通过它获取数据的 xff0c proc meminfo所包含的信息比 free 等
  • 看完秒懂:Linux DMA mapping机制分析

    说明 xff1a Kernel版本 xff1a 4 14ARM64处理器 xff0c Contex A53 xff0c 双核使用工具 xff1a Source Insight 3 5 xff0c Visio 1 概述 DMA xff08 D
  • linux网络编程-多进程实现TCP并发服务器

    服务端流程步骤 socket函数创建监听套接字lfd bind函数将监听套接字绑定ip和端口 listen函数设置服务器为被动监听状态 xff0c 同时创建一条未完成连接队列 xff08 没走完tcp三次握手流程的连接 xff09 xff0
  • Linux内核中断下半部工作队列(work queue)

    工作队列work queue 工作队列 xff08 work queue xff09 是中断下半部的一种实现机制 xff0c 主要用于耗时任务处理 xff0c 由内核线程代表进程执行 工作队列运行于进程上下文 xff0c 因此允许阻塞 运行
  • 手把手带你部署Ceph集群

    前言 xff1a Ceph作为开源的分布式文件系统 xff0c 可以轻松地将存储容量扩展到PB以上并拥有不错的性能 Ceph提供对象存储 块存储和文件系统三种存储方式 xff0c 如果不想花时间安装ceph xff0c 可以通过ceph d
  • Linux 内核安全增强—— stack canary

    一 背景知识 aarch64的函数栈 1 栈生长方向与push pop操作 栈是一种运算受限的线性表 入栈的一端为栈顶 xff0c 另一端则为栈底 其生长方向和操作顺序理论上没有限定 而在aarch64平台上 栈是向低地址方向增长的 STA
  • Linux下Makefile的简单编写与使用

    Makefile 一个工程文件中的源文件可能有很多 xff0c 并且不同的功能 模块等都放在不同的目录中 xff0c 常规的编译已经不能高效化的处理这样的问题 xff0c 而Makefile就是为解决这一问题而来 Makefile一旦写好
  • STM32 USART 串口DMA收发注意事项

    正常情况这里不介绍 目录 1 低波特率情况 xff0c 接收信号可能会出现干扰 2 波特率300时 xff0c DMA接收无法工作 3 波特率1200时DMA发送 4 具体现象如下 环境 xff1a 主频72M STM32F103C8 注意
  • STM32学习笔记———几种简单传感器的数据读取

    引言 传感器正如计算机的眼睛 从广义上讲 xff0c 传感器就是一种能感知外界信息 xff0c 并将这些信息按照一定规律转换成可用的电信号或其他形式的输出信号的装置 xff0c 达到对信息的存储 xff0c 传输 xff0c 控制的目的 本
  • 基于STM32F103C8T6的USART1串口的中断接收

    一 串口介绍 二 项目所需硬件 1 USB转串口模块 三 项目代码 一 串口介绍 USART Universal Synchronous Asynchronous Receiver Transmitter 通用同步 异步串行接收 发送器 U
  • 第5讲—寄存器编程

    编程方式两种 xff0c 一种是寄存器编程 xff0c 一种是函数库编程 什么是寄存器 stm32芯片 61 ARM内核生产Cortex内核 43 st公司 xff08 在内核基础上 xff09 开发stm32 寄存器是用来地址操作的 寄存
  • C语言运行HTTP代码示例

    include lt iostream gt include lt algorithm gt include lt cstring gt include 34 curl curl h 34 usingnamespace std static
  • 在Linux上实现HTTP请求

    在Linux上实现HTTP请求是一种非常有用的技能 xff0c 有时候我们需要从Web服务器获取数据 xff0c 而不是使用浏览器发起网络调用 HTTP是一种常用的网络协议 xff0c 可以用于在Linux上实现HTTP请求 要在Linux
  • Linux下设置堆栈系统参数

    Linux系统下有几个与堆栈相关的系统参数 xff1a 1 ulimit s xff1a 此参数用于限制进程的堆栈大小 可以使用该命令来查看和更改进程的堆栈大小限制 2 proc sys kernel stack protect xff1a
  • Leetcode每日一题——“消失的数字”

    各位CSDN的uu们你们好呀 xff0c 今天 xff0c 小雅兰又开新专栏了 xff0c 以后会在Leetcode上面进行刷题 xff0c 尽量每天写一道 xff0c 请大家监督我 xff01 xff01 xff01 好啦 xff0c 让
  • Leetcode每日一题——“轮转数组”

    各位CSDN的uu们你们好呀 xff0c 今天 xff0c 小雅兰的内容是轮转数组 xff0c 下面 xff0c 让我们进入轮转数组的世界吧 小雅兰之前其实就已经写过了字符串旋转的问题了 xff1a C语言刷题 xff08 7 xff09

随机推荐

  • Python一行命令搭建HTTP服务器并外网访问【内网穿透】

    文章目录 1 前言2 本地http服务器搭建2 1 Python的安装和设置2 2 Python服务器设置和测试 3 cpolar的安装和注册3 1 Cpolar云端设置3 2 Cpolar本地设置 4 公网访问测试5 结语 转载自远程内网
  • 顺序表(更新版)——“数据结构与算法”

    各位CSDN的uu们你们好呀 xff0c 今天小雅兰又来更新新专栏啦 xff0c 其实之前我就已经写过了顺序表的内容 xff0c 只是之前的内容不是最新版的顺序表 xff0c 现在 xff0c 我来更新一下最新版的顺序表 xff0c 下面
  • Leetcode每日一题——“移除元素”

    各位CSDN的uu们你们好呀 xff0c 小雅兰又来啦 xff0c 今天 xff0c 小雅兰的内容是移除元素 xff0c 下面 xff0c 让我们进入Leetcode的世界吧 说明 为什么返回数值是整数 xff0c 但输出的答案是数组呢 请
  • Leetcode每日一题——“回文数”

    各位CSDN的uu们 xff0c 你们好呀 xff0c 今天小雅兰又来刷力扣啦 xff0c 今天的题目是回文数 xff0c 下面 xff0c 让我们进入回文数的世界吧 示例 1 xff1a 输入 xff1a x 61 121 输出 xff1
  • 【社区图书馆】《新程序员005:开源深度指南 & 新金融背后的科技力量》

    各位CSDN的uu们你们好呀 xff0c 今天 xff0c 小雅兰来给大家推荐一本书 xff0c 此书的书名为新程序员005 xff1a 开源深度指南 amp 新金融背后的科技力量 xff0c 为什么小雅兰今天要给大家推荐这样一本书呢 xf
  • Nodejs快速搭建简单的HTTP服务器,并发布公网远程访问

    文章目录 前言1 安装Node js环境2 创建node js服务3 访问node js 服务4 内网穿透4 1 安装配置cpolar内网穿透4 2 创建隧道映射本地端口 5 固定公网地址 转载自内网穿透工具的文章 xff1a 使用Node
  • Leetcode每日一题——“合并两个有序数组”

    各位CSDN的uu们你们好呀 xff0c 又到小雅兰的愉快题解时候啦 xff0c 今天 xff0c 我们的题目内容是合并两个有序数组 xff0c 下面 xff0c 让我们进入合并两个有序数组的世界吧 示例 1 xff1a 输入 xff1a
  • Leetcode每日一题——“链表的中间结点”

    各位CSDN的uu们你们好呀 xff0c 今天 xff0c 小雅兰愉快的刷题内容是链表的中间结点 嘿嘿 xff0c 小雅兰的单链表还在偷懒ing xff0c 一直没有更新 xff0c 最近应该会更新出来 下面 xff0c 就让我们进入链表的
  • VRPN-体验

    VRPN简介 VRPN提供封装在库里的一套类 xff0c 在VR系统中 xff0c 用来为应用程序和物理外设提供网络传输接口 详细点击这里 VRPN源码获取 git clone https github com vrpn vrpn git
  • 单链表——“数据结构与算法”

    各位CSDN的uu们你们好呀 xff0c 今天 xff0c 小雅兰的内容终于是我们心心念念的单链表啦 xff0c 这一块呢 xff0c 是一个很重要的部分 xff0c 也是一个对目前的我来说 xff0c 比较困难的部分 xff0c 下面 x
  • springboot服务端接口外网远程调试,并实现HTTP服务监听【内网穿透】

    文章目录 前言1 本地环境搭建1 1 环境参数1 2 搭建springboot服务项目 2 内网穿透2 1 安装配置cpolar内网穿透2 1 1 windows系统2 1 2 linux系统 2 2 创建隧道映射本地端口2 3 测试公网地
  • MCSM面板一键搭建我的世界服务器-外网远程联机【内网穿透】

    文章目录 前言1 Mcsmanager安装2 创建Minecraft服务器3 本地测试联机4 内网穿透4 1 安装cpolar内网穿透4 2 创建隧道映射内网端口 5 远程联机测试6 配置固定远程联机端口地址6 1 保留一个固定TCP地址6
  • 初识MySQL数据库——“MySQL数据库”

    各位CSDN的uu们你们好呀 xff0c 小雅兰好久没有更文啦 xff0c 确实是心有余而力不足 xff0c 最近学习的内容太难了 xff0c 这篇博客又是小雅兰的新专栏啦 xff0c 主要介绍的是一些MySQL数据库的知识点 xff0c
  • Windows10本地搭建网站教程【内网穿透】

    文章目录 概述1 搭建一个静态Web站点2 本地浏览测试站点是否正常3 本地站点发布公网可访问3 1 安装cpolar内网穿透3 2 创建隧道映射公网地址3 3 获取公网URL地址 4 公网远程访问内网web站点5 配置固定二级子域名5 1
  • MySQL环境搭建——“MySQL数据库”

    各位CSDN的uu们你们好呀 xff0c 小雅兰又来啦 xff0c 好久没有更文啦 xff0c 今天继续 xff01 xff01 xff01 今天小雅兰的内容是MySQL环境搭建 xff0c 下面 xff0c 让我们进入MySQL数据库的世
  • 在树莓派上搭建WordPress博客网站【内网穿透】

    文章目录 概述安装 PHP安装MySQL数据库安装 Wordpress设置您的 WordPress 数据库设置 MySQL MariaDB创建 WordPress 数据库 WordPress configuration将WordPress站
  • 双链表——“数据结构与算法”

    各位CSDN的uu们你们好呀 xff0c 今天 xff0c 小雅兰又回来了 xff0c 到了好久没有更新的数据结构与算法专栏 xff0c 最近确实发现自己有很多不足 xff0c 需要学习的内容也有很多 xff0c 所以之后更新文章可能不会像
  • Windows在外远程桌面控制macOS【macOS自带VNC远程】

    文章目录 前言1 测试局域网内远程控制1 1 macOS打开屏幕共享1 2 测试局域网内VNC远程控制 2 测试公网远程控制2 1 macOS安装配置cpolar内网穿透2 2 创建tcp隧道 xff0c 指向5900端口 3 测试公网远程
  • 初学正点原子Ministm32板串口实验

    本章将实现如下功能 xff1a STM32 通过串口和上位机的对话 xff0c STM32 在收到上位机发过来的字符串后 xff0c 原原本本的返回给上位机 本章分为如下几个小节 xff1a 1 STM32串口简介 2 硬件设计 3 软件设
  • Qt网络通信实战(聊天室小项目TCP实现)

    一 UDP与TCP的区别 用一个表格来显示这两者的区别 比较项TCPUDP是否连接面向连接无连接传输是否可靠可靠不可靠流量控制提供不提供工作方式全双工可以是全双工应用场合大量数据少量数据速度慢 快 我们这里采用TCP 当有新的连接出现时就会