qt tcp通讯

news2024/11/27 2:47:47

TCP 协议(Transmission Control Protocol)全称是传输控制协议是一种面向连接的、可靠的、

基于字节流的传输层通信协议。

tcp服务端使用QTcpServer、QTcpSocket。

tcp客户端使用QTcpSocket

1.在工程文件(工程文件.pro)中的第一行添加network 如

QT += core gui network //network是添加之后的

2.引用头文件

#include<QTcpServer>//监听套接字

#include<QTcpSocket>//通信套接字

服务端

1.创建QTcpServer对象

2.启动服务器(监听)调用成员方法listen(QHostAddress::Any,端口号)

3.当有客户端连接时候会发送newConnection信号,触发槽函数接受连接(调用 nextPendingConnection函数得到一个与客户端通信的套接字QTcpSocket),通过QTcpSocket对象调用peerAddress、peerPort得到客户端的ip地址和端口。

4.QTcpsocket发送数据用成员方法write

5.读数据当客户端有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据。

和客户端建立连接之后用于通信的 QTcpSocket 套接字对象,它是 QTcpServer 的一个子对象,当 QTcpServer 对象析构的时候会自动析构这个子对象,当然也可自己手动析构,建议用完之后自己手动析构这个通信的 QTcpSocket 对象

超时接受连接函数waitForNewConnection

bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR);

msec:指定阻塞的最大时长,单位为毫秒(ms)

timeout:传出参数,如果操作超时 timeout 为 true,没有超时 timeout 为 false

常用信号

  1. 每次有新连接可用时都会发出 newConnection () 信号

  1. 当接受新连接导致错误时,将发射acceptError信号


#ifndef CTCPSERVER_H
#define CTCPSERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>

class CTcpServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit CTcpServer(QTcpServer *parent = nullptr);

    //发送信息到已连接的所有客户机
    void sendData(QString data);
signals:
    //通过该信号传递接收到的数据
    void recvDataSignal(QString data);
public slots:
    //当有新连接时的槽函数
    void newClient();
    //当有数据来时的槽函数
    void readyReadData();
private:
    QList<QTcpSocket *> m_clientList;   //存放客户端socket的容器
};

#endif // CTCPSERVER_H

#include "CTcpServer.h"
#include <QTcpServer>

CTcpServer::CTcpServer(QTcpServer *parent) : QTcpServer(parent)
{
    //设置可以连接的ip和端口号(此处为任意ip且端口号为6666的可以连接);若要指定ip,设置第一个参数即可
    this->listen(QHostAddress::Any, 8866);
    //连接相关的信号槽
    connect(this, &CTcpServer::newConnection, this, &CTcpServer::newClient);
}

void CTcpServer::sendData(QString data)
{
    //遍历客户端列表,将数据发送到所有客户端中(类似广播)
    foreach (QTcpSocket *temp, m_clientList)
    {
        temp->write(data.toLocal8Bit(), data.length());
    }
}

void CTcpServer::newClient()
{
    //循环获取客户端socket
    while (this->hasPendingConnections())
    {
        QTcpSocket *clientTemp = this->nextPendingConnection();   //拿到当前的socket
        m_clientList.append(clientTemp);    //将当前socket添加到列表中(方便操作)
        connect(clientTemp, &QTcpSocket::readyRead, this, &CTcpServer::readyReadData);
    }
}

void CTcpServer::readyReadData()
{
    //拿到发送信号的客户端指针,通过该指针读取数据
    QTcpSocket *curClient = dynamic_cast<QTcpSocket *>(sender());
    emit recvDataSignal(curClient->readAll());
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtNetwork>
#include "ctcpserver.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_m_listenButton_clicked();

    void on_m_sendButton_clicked();

    void on_m_closeButton_clicked();

    void on_m_exitButton_clicked();

    void on_appendData(QString data);    //将接收的数据显示

private:
    Ui::MainWindow *ui;

    CTcpServer *m_pserver;
};

#endif // MAINWINDOW_H

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_pserver(nullptr)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;

    if(m_pserver)
    {
        m_pserver->close();
        delete m_pserver;
        m_pserver = nullptr;
    }

}

void MainWindow::on_m_listenButton_clicked()
{
    m_pserver = new CTcpServer();
    connect(m_pserver, &CTcpServer::recvDataSignal, this, &MainWindow::on_appendData);

}

void MainWindow::on_m_sendButton_clicked()
{
    m_pserver->sendData(ui->m_sendlineEdit->text());

}

void MainWindow::on_m_closeButton_clicked()
{
    if(m_pserver)
    {
        m_pserver->close();
        delete m_pserver;
        m_pserver = nullptr;
    }


}

void MainWindow::on_m_exitButton_clicked()
{


}

void MainWindow::on_appendData(QString data)
{
    ui->m_showtextBrowser->append(data);
}

客户端

1.创建QTcpSocket对象

2.链接服务器connectToHost(QHostAddress("ip"),端口号)

3.QTcpsocket发送数据用成员方法write

4.读数据当对方有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据

常用信号

readyRead

如果该类对象发射出 readyRead() 信号,说明对端发送的数据达到了,之后就可以调用 read 函数接收数据了。

connected

调用 connectToHost() 函数连接TCP服务器并成功建立连接之后发出 connected() 信号

disconnected

在套接字断开连接时发出 disconnected() 信号




#ifndef CTCPSOCKET_H
#define CTCPSOCKET_H

#include <QObject>
#include <QTcpSocket>

class CTcpSocket : public QTcpSocket
{
    Q_OBJECT
public:
    explicit CTcpSocket(QTcpSocket *parent = nullptr);
    //通过改函数发送数据
    void sendData(QString data);
signals:
    //通过该信号传递接收到的数据
    void recvDataSignal(QString data);
public slots:
    //读取数据的槽函数
    void readyReadData();
};
#endif // CTCPSOCKET_H

#include "CTcpSocket.h"
#include <QHostAddress>

CTcpSocket::CTcpSocket(QTcpSocket *parent) : QTcpSocket(parent)
{
    //连接相应槽函数
    connect(this, &CTcpSocket::readyRead, this, &CTcpSocket::readyReadData);

    //指定ip且端口号为8866, (QHostAddress中指定的ip需本机存在或能连接到才可使用)
    this->connectToHost(QHostAddress("127.0.0.1"), 8866);
}

void CTcpSocket::sendData(QString data)
{
    this->write(data.toUtf8());
}

void CTcpSocket::readyReadData()
{
    emit recvDataSignal(this->readAll());
}

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtNetwork>
#include "ctcpsocket.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_m_connectButton_clicked();

    void on_m_sendButton_clicked();

    void on_m_closeButton_clicked();

    void on_appendData(QString data);    //将接收的数据显示


private:
    Ui::MainWindow *ui;
    CTcpSocket *m_client;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    m_client(nullptr)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
    if(m_client)
    {
        m_client->close();
        delete m_client;
        m_client = nullptr;
    }
}

void MainWindow::on_m_connectButton_clicked()
{
    m_client = new CTcpSocket;
    connect(m_client, &CTcpSocket::recvDataSignal, this, &MainWindow::on_appendData);

}

void MainWindow::on_m_sendButton_clicked()
{
    m_client->sendData(ui->m_sendlineEdit->text());

}

void MainWindow::on_m_closeButton_clicked()
{
    if(m_client)
    {
        m_client->close();
        delete m_client;
        m_client = nullptr;
    }

}

void MainWindow::on_appendData(QString data)
{
    ui->m_showtextBrowser->append(data);
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WeSpeaker支持C++部署链路

WeSpeaker正式更新C部署链路&#xff0c;推理引擎使用OnnxRuntime&#xff0c;支持从语音中提取Speaker Embedding信息&#xff0c;代码详见WeSpeaker/runtime[1]。 Libtorch和onnx的选择? Speaker Embedding提取任务流程简单&#xff0c;并且声纹模型&#xff08;如ResNet\E…

前端js学习

1. js入门 1.1 js是弱类型语言 1.2 js使用方式 1.2.1 在script中写 1.2.2 引入js文件 1.2.3 优先级 1.3 js查错方式 1.4 js变量定义 1.4 js数据类型 数据类型英文表示示例数值类型number1.1 1字符串类型string‘a’ ‘abc’ “abc”对象类型object布尔类型booleannumber函数…

包教包会的Node.js

一、简介 1、什么是Node.js 简单的说 Node.js 就是运行在服务端的 JavaScript。 Node.js是一个事件驱动I/O服务端JavaScript环境&#xff0c;基于Google的V8引擎&#xff0c;V8引擎执行Javascript的速度非常快&#xff0c;性能非常好。 2、Node.js有什么用 如果你是一个前…

风起|微软突发声明:始终严格保护并捍卫用户隐私

开放隐私计算 3 月 9 日消息&#xff0c;微软中国今天发布了声明&#xff0c;针对日前国内某些自媒体传播的有关个人用户使用微软消费类产品和服务的误解&#xff0c;特做了相关说明。微软表示&#xff0c;微软始终严格遵守个人隐私保护与数据安全等方面的各项法律法规。微软提…

深眸科技突破革新机器视觉技术,加速实现工业自动化与智能化发展

随着现代生活水平的不断提高&#xff0c;人们对产品的品质需求持续提升&#xff0c;且在智能制造这一大环境下&#xff0c;多数制造企业积极转型&#xff0c;寻求更高效的检测方式。而机器视觉及相关技术的发展&#xff0c;让多数公司通过创新机器视觉应用产品&#xff0c;以及…

面试必会-MySQL篇

1. Mysql查询语句的书写顺序Select [distinct ] <字段名称>from 表1 [ <join类型> join 表2 on <join条件> ]where <where条件>group by <字段>having <having条件>order by <排序字段>limit <起始偏移量,行数>2. Mysql查询语…

vue3使用nextTick

发现nextTick必须放在修改一个响应式数据之后&#xff0c;才会在onUpdated之后被调用&#xff0c;如果nextTick是放在所有对响应式数据修改之前&#xff0c;则nextTick里面的回调函数会在onBeforeUpdate方法执行前就被调用了。可是nextTick必须等到onUpdated执行完成之后执行&a…

Android代码重构系列-02-使用Kotlin协程实现一个支持任务编排的轻量级启动器

前言虽然本文的主题是启动器&#xff0c;但是笔者不打算去写怎么做启动优化&#xff0c;以及怎么实现一个完美的启动器。关于开源的第三方Android启动器已经有很多优秀的轮子了&#xff0c;比如阿里巴巴的alpha&#xff0c;参考 alpha 并改进其部分细节的Anchors&#xff0c;St…

Mybatis框架源码笔记(七)之Mybatis中类型转换模块(TypeHandler)解析

1、JDBC的基本操作回顾 这里使用伪代码概括一下流程: 对应数据库版本的驱动包自行下载加载驱动类 (Class.forName("com.mysql.cj.jdbc.Driver"))创建Connection连接: conn DriverManager.getConnection("jdbc:mysql://数据库IP:port/数据库名称?useUnico…

最新消息:2023年软考高项教材改版!

最新通知&#xff1a;从2023年上半年软考开始信息系统项目管理师考试将依据新版考试大纲进行。 给备考高项的朋友的一些建议&#xff1a; 备考资源&#xff1a; 【腾讯文档】软考各科资料分享 https://docs.qq.com/doc/DTVN1SWtFZHdicUNp 复习方法&#xff1a; 选择题 选择题…

ChatGPT,乌合之众的疯狂

最近ChatGPT有多火爆就不用我说了。公司里&#xff0c;从CEO到技术人员&#xff0c;乃至于门口的保安、食堂的大婶&#xff0c;没有一个不会聊两句ChatGPT的。连我20年未见的小学同学、三线城市警官&#xff0c;都问我这东西能不能给领导写汇报材料。 用不了多久&#xff0c;家…

颠覆推特VS改造推特:什么是去中心化社交的正确姿势?

去年&#xff0c;“钢铁侠”伊隆马斯克收购了全球最大的社交媒体之一——推特。推特成立于2006年&#xff0c;是一个“公民广场”&#xff0c;允许大家公开发表观点和内容。用户可以关注自己喜欢的账号&#xff0c;也可以点赞转发评论他人的推文&#xff0c;中国的微博便是照搬…

【halcon】轮廓拟合相关算子

涉及函数 edges_sub_pix 寻找边缘 edges_sub_pix (Image, Edges, canny, 1, 10, 20) 后面三个参数&#xff0c;越小&#xff0c;找到的细节越多。这个是对应录波器为canny时。 canny滤波器用的最多。 segment_contours_xld 将连续的轮廓进行分段&#xff0c;按圆弧或者执…

JUC(七)

1.线程安全集合类 1>.线程安全集合类可以分为三大类: ①.遗留的(/旧的)线程安全集合,如:Hashtable,Vector; ②.使用Collections装饰的线程安全集合,如: Collections.synchronizedCollectionCollections.synchronizedListCollections.synchronizedMapCollections.synchroniz…

window通过wsl启动appsmith源码

window通过wsl启动appsmith前端后端前言appsmith前端本地启动WSL安装下载ubuntu升级wsl到wsl2ubuntu安装环境环境要求Ubuntu环境配置node下载解压运行[源码](https://www.appsmith.com/)本地访问后端appsmith后台本地启动启动mongo、rediswsl ubuntu中启动后台试试流程总结最后…

缓存双写一致性之更新策略探讨

问题由来 数据redis和MySQL都要有一份&#xff0c;如何保证两边的一致性。 如果redis中有数据&#xff1a;需要和数据库中的值相同如果redis中没有数据&#xff1a;数据库中的值是最新值&#xff0c;且准备会写redis 缓存操作分类 自读缓存读写缓存&#xff1a; &#xff0…

关于vuex的使用

1.首先安装vuex npm install vuex --save 这时如果直接安装vuex&#xff0c;不指定版本的话&#xff0c;就会直接安装最新的vuex的版本。所以会出现报错。 报错就安装这个 npm install --save vuex3 2.创建文件夹&#xff0c; 有的时候安装好会自动创建vuex的文件夹 &#xf…

Python解题 - CSDN周赛第35期 - 不算题解的题解

本期四道题还是全考过&#xff0c;题解在网上也都搜得到。。。只好继续水一份不算题解的题解。 第一题&#xff1a;交换后的or 给定两组长度为n的二进制串&#xff0c;请问有多少种方法在第一个串中交换两个不同位置上的数字&#xff0c;使得这两个二进制串“或”的结果发生改…

案例01-修改数据redis没有同步更新

目录 一&#xff1a;背景介绍 二&#xff1a;思路&方案 三&#xff1a;过程 1.修改数据没有删除缓存 2.修改数据删除了缓存 四&#xff1a;总结 五&#xff1a;升华 一&#xff1a;背景介绍 redis中存储了关于一个课程下多个班级的信息。但是难免会在一个课程下添加新…

pandas 数据预处理+数据概览 处理技巧整理(持续更新版)

这篇文章主要是整理下使用pandas的一些技巧&#xff0c;因为经常不用它&#xff0c;这些指令忘得真的很快。前段时间在数模美赛中已经栽过跟头了&#xff0c;不希望以后遇到相关问题的时候还去网上查&#xff08;主要是太杂了&#xff09;。可能读者跟我有一样的问题&#xff0…