Qt之超简单的TCP通信(自定义TCP通信类,含源码+注释)
文章目录
- 一、TCP通信示例图
- 二、TCP使用前的准备
- 三、自定义TCP通信类的两种方法
- 四、源码(含注释)
- TCP Server
- CTcpServer.h
- CTcpServer.cpp
- TCP Client
- CTcpSocket.h
- CTcpSocket.cpp
- CMainWindow类(自定义TCP通信类的调用)
- CMainWindow.h
- CMainWindow.cpp
- 总结
- 相关文档
一、TCP通信示例图
下图为TCP通信的简单界面,能是实现简单的TCP连接和发送信息,源码在本文第四节(源码含详细注释)
提示:不会使用Qt设计师设计界面的小伙伴点击这里
二、TCP使用前的准备
- 在pro文件中添加 “QT += network”(需要添加后才能使用网络通信)
- TCP发送可以通过write函数
- TCP读取可以通过read函数
- TCP收到新信息时会发出readyRead信号
- TCP服务端有新连接时会发出newConnection信号
- TCP服务端需要保存连接进来的客户端指针(方便通信)
三、自定义TCP通信类的两种方法
- 类继承对应的TCP类,通过this指针实现TCP操作(本文使用该方法)
- 类中包含对应的TCP类对象,通过该对象实现TCP操作
注:以上两种方法最好不要合并使用,如果指针/对象使用不对有可能会出现如下类似的问题:QIODevice::write (QTcpSocket): device not open
四、源码(含注释)
TCP Server
CTcpServer.h
#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
CTcpServer.cpp
#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()
{//循环获取客户端socketwhile (this->hasPendingConnections()){QTcpSocket *clientTemp = this->nextPendingConnection(); //拿到当前的socketm_clientList.append(clientTemp); //将当前socket添加到列表中(方便操作)connect(clientTemp, &QTcpSocket::readyRead, this, &CTcpServer::readyReadData);}
}void CTcpServer::readyReadData()
{//拿到发送信号的客户端指针,通过该指针读取数据QTcpSocket *curClient = dynamic_cast<QTcpSocket *>(sender());emit recvDataSignal(curClient->readAll());
}
TCP Client
CTcpSocket.h
#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
CTcpSocket.cpp
#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("192.168.13.1"), 8866);
}void CTcpSocket::sendData(QString data)
{this->write(data.toUtf8());
}void CTcpSocket::readyReadData()
{emit recvDataSignal(this->readAll());
}
CMainWindow类(自定义TCP通信类的调用)
CMainWindow.h
#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H#include <QMainWindow>
#include "CTcpServer.h"
#include "CTcpSocket.h"namespace Ui {class CMainWindow;
}class CMainWindow : public QMainWindow
{Q_OBJECT
public:explicit CMainWindow(QWidget *parent = 0);~CMainWindow();private slots:void on_connectBtn_clicked(); //连接void on_sendBtn_clicked(); //发送void on_appendData(QString data); //将接收的数据显示private:Ui::CMainWindow *ui;CTcpServer *m_server;CTcpSocket *m_client;
};
#endif // CMAINWINDOW_H
CMainWindow.cpp
#include "CMainWindow.h"
#include "ui_CMainWindow.h"CMainWindow::CMainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::CMainWindow), m_server(nullptr), m_client(nullptr){ui->setupUi(this);
}CMainWindow::~CMainWindow()
{if(nullptr != m_server){delete m_server;m_server = nullptr;}if(nullptr != m_client){delete m_client;m_client = nullptr;}delete ui;
}void CMainWindow::on_connectBtn_clicked()
{//当连接后直接返回if("已连接" == ui->connectBtn->text())return;if(0 == ui->typeComboBox->currentIndex()){m_server = new CTcpServer;connect(m_server, &CTcpServer::recvDataSignal, this, &CMainWindow::on_appendData);}else{m_client = new CTcpSocket;connect(m_client, &CTcpSocket::recvDataSignal, this, &CMainWindow::on_appendData);}//设置按钮文本ui->connectBtn->setText("已连接");
}void CMainWindow::on_sendBtn_clicked()
{if(0 == ui->typeComboBox->currentIndex()){m_server->sendData(ui->textEdit->toPlainText());}else{m_client->sendData(ui->textEdit->toPlainText());}
}void CMainWindow::on_appendData(QString data)
{ui->textBrowser->append(data);
}
总结
TCP通信中不像UDP通信中两端都要绑定IP和端口号,并且TCP通信也更加安全。
在本文中不论时服务器还是客户端的IP和端口号都是代码写死的,若是需要能人性化的设置,在界面中添加两个QLineEdit且在自定义的通信类中添加设置IP和端口号的接的,调用该接口并将文本框中的对应值传入即可。若是有兴趣还可实现数据校验、重连、断开连接、指定客户端发送等功能。
相关文档
自定义UDP类
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除
Qt之超简单的TCP通信(自定义TCP通信类,含源码+注释)相关推荐
- Qt之语言家的简单使用(一)(Qt翻译UI,Qt Linguist的使用,含源码+注释)
文章目录 一.翻译程序示例图 二.流程须知(个人理解) 三.关于对话框中QDialogButtonBox翻译的操作 四.源码 CLinguistTest.h CLinguistTest.cpp CLi ...
- Qt数据库练习之QSqlTableModel的使用(MySql数据库示例,含源码+注释)
文章目录 一.操作示例 1.1 修改记录(数据) 1.2 添加记录(数据) 1.3 删除记录(数据) 1.4 取消操作 1.5 排序操作 1.6 查询操作 二.了解QSqlTableModel 三.源 ...
- SwiftUI 动画大全之 五彩纸屑特效含三角形、五星、钻石与自定义图像 (教程含源码)
实战需求 SwiftUI 动画大全之 五彩纸屑特效含三角形.五星.钻石与自定义图像 (教程含源码) 下雨了,五彩纸屑!SAConfettiView是向您的应用程序添加有趣.多彩的五彩纸屑并让用户感到有 ...
- Qt之天气预报——界面优化篇(含源码+注释)
一.界面优化效果 下方为界面优化完成和优化前的效果对比. 优化前: 优化后: 二.优化内容 添加标题栏 添加图片(图图标素材源自阿里巴巴矢量图标库) 更新UI内容(微调大小.布局比例) 添加鼠标事件函 ...
- Flutter 组件之 Flutter高级自定义TabBar(教程含源码)
实战需求 Flutter 组件之 Flutter高级自定义TabBar(教程含源码) 本文价值与收获 看完本文后,您将能够作出下面的界面 实战代码 import 'package:flutter/ma ...
- 简单音乐播放器html+css+基础vue+含源码,有搜索和播放mv功能,代码可直接复制用。
题目:html+css+基础vue实现的简单音乐播放器(含源码),有搜索和播放mv功能,代码可直接复制用. 问题描述: 如果vue刚入门,掌握一些基础语法后就可以写一个简单的音乐播放器来练练手~~如果 ...
- Qt小游戏之数字华容道(百行代码搭雏形,可玩;含源码+注释)
文章目录 一.数字华容道,样图如下 二.废话少说直接上代码 1.首先是代码文件分析 2.CLabel的源码 3.CMainWindow的源码 4.main文件 总结 一.数字华容道,样图如下 相信大家 ...
- 【.net+jquery】绘制自定义表单(含源码)
前言 两年前的时候就想做一个类似的功能,当时思路大家都讨论好了,诸多原因最终还是夭折了.没想到两年多后再这有重新提出要写一个绘制表单的功能.对此也是有点小激动呢?总共用时8.5天的时间基本功能也就实现 ...
- SwiftUI 界面大全之个人简历界面支持自定义字体(教程含源码)
实战需求 个人简历界面 实现自定义字体 图文混合 本文价值与收获 看完本文后,您将能够作出下面的界面 看完本文您将掌握的技能 设置自定义字体 Text("张xxx").font(F ...
最新文章
- golang go-restful RESTful框架 简介
- 关于团队发展的若干想法(欢迎讨论)
- Docker图形化管理工具之Portainer
- leetcode 238. Product of Array Except Self | 238. 除自身以外数组的乘积(Java)
- 首发!《长安十二时辰背后的技术秘籍》正式公开,速来下载
- (27)FPGA面试题动态时序模拟
- PHP中等良好优秀,成绩优秀,中等,良好怎么分的啊?分为哪几个?
- java split 坑
- Servlet技术 - Servlet应用
- 罗永浩发声:我的努力很可能失败 但好产品一定要赢
- Win11如何重置电脑 Win11重置电脑教程
- 个人财务管理系统设计与实现
- 使用include-what-you-use优化编译速度
- 配置web.xml文件时报The word ‘***‘ is not correctly spelled的解决方案
- 图片怎么转换为jpg格式的?照片如何在线转格式?
- [531]微信之wxpy库(基于itchat库)
- c语言0x前缀的作用,有趣的问题,C语言程序中,为什么十六进制数字以前缀0x开头呢?...
- FastDB 高效率的内存数据库系统
- 回归分析中的相关度(Corr)和R^2
- Python 数据结构 之 串 的链式存储结构
热门文章
- D. Ela and the Wiring Wizard floyd/思维
- 零基础CSS入门教程(8)–id选择器
- 机器学习(五)——时间序列ARIMA模型
- 一台服务器最大能支持多少条TCP连接
- Java常见面试题—final 在 java 中有什么作用?
- 【技术栈——00042】Docker网络端口指定的两种方式
- 安卓 linux it之家,IT之家安卓版 7.07:紧凑排版+适配华为小米魅族OV系统级推送等...
- 莫烦python神经网络进化(NeuroEvolution)之最全篇
- 什么是缓冲区溢出?有什么危害?其原因是什么?
- 量化投资中常遇到的两个问题