文章目录

  • 一、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使用前的准备

  1. 在pro文件中添加 “QT += network”(需要添加后才能使用网络通信)
  2. TCP发送可以通过write函数
  3. TCP读取可以通过read函数
  4. TCP收到新信息时会发出readyRead信号
  5. TCP服务端有新连接时会发出newConnection信号
  6. TCP服务端需要保存连接进来的客户端指针(方便通信)

三、自定义TCP通信类的两种方法

  1. 类继承对应的TCP类,通过this指针实现TCP操作(本文使用该方法)
  2. 类中包含对应的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通信类,含源码+注释)相关推荐

  1. Qt之语言家的简单使用(一)(Qt翻译UI,Qt Linguist的使用,含源码+注释)

    文章目录 一.翻译程序示例图 二.流程须知(个人理解) 三.关于对话框中QDialogButtonBox翻译的操作 四.源码 CLinguistTest.h CLinguistTest.cpp CLi ...

  2. Qt数据库练习之QSqlTableModel的使用(MySql数据库示例,含源码+注释)

    文章目录 一.操作示例 1.1 修改记录(数据) 1.2 添加记录(数据) 1.3 删除记录(数据) 1.4 取消操作 1.5 排序操作 1.6 查询操作 二.了解QSqlTableModel 三.源 ...

  3. SwiftUI 动画大全之 五彩纸屑特效含三角形、五星、钻石与自定义图像 (教程含源码)

    实战需求 SwiftUI 动画大全之 五彩纸屑特效含三角形.五星.钻石与自定义图像 (教程含源码) 下雨了,五彩纸屑!SAConfettiView是向您的应用程序添加有趣.多彩的五彩纸屑并让用户感到有 ...

  4. Qt之天气预报——界面优化篇(含源码+注释)

    一.界面优化效果 下方为界面优化完成和优化前的效果对比. 优化前: 优化后: 二.优化内容 添加标题栏 添加图片(图图标素材源自阿里巴巴矢量图标库) 更新UI内容(微调大小.布局比例) 添加鼠标事件函 ...

  5. Flutter 组件之 Flutter高级自定义TabBar(教程含源码)

    实战需求 Flutter 组件之 Flutter高级自定义TabBar(教程含源码) 本文价值与收获 看完本文后,您将能够作出下面的界面 实战代码 import 'package:flutter/ma ...

  6. 简单音乐播放器html+css+基础vue+含源码,有搜索和播放mv功能,代码可直接复制用。

    题目:html+css+基础vue实现的简单音乐播放器(含源码),有搜索和播放mv功能,代码可直接复制用. 问题描述: 如果vue刚入门,掌握一些基础语法后就可以写一个简单的音乐播放器来练练手~~如果 ...

  7. Qt小游戏之数字华容道(百行代码搭雏形,可玩;含源码+注释)

    文章目录 一.数字华容道,样图如下 二.废话少说直接上代码 1.首先是代码文件分析 2.CLabel的源码 3.CMainWindow的源码 4.main文件 总结 一.数字华容道,样图如下 相信大家 ...

  8. 【.net+jquery】绘制自定义表单(含源码)

    前言 两年前的时候就想做一个类似的功能,当时思路大家都讨论好了,诸多原因最终还是夭折了.没想到两年多后再这有重新提出要写一个绘制表单的功能.对此也是有点小激动呢?总共用时8.5天的时间基本功能也就实现 ...

  9. SwiftUI 界面大全之个人简历界面支持自定义字体(教程含源码)

    实战需求 个人简历界面 实现自定义字体 图文混合 本文价值与收获 看完本文后,您将能够作出下面的界面 看完本文您将掌握的技能 设置自定义字体 Text("张xxx").font(F ...

最新文章

  1. golang go-restful RESTful框架 简介
  2. 关于团队发展的若干想法(欢迎讨论)
  3. Docker图形化管理工具之Portainer
  4. leetcode 238. Product of Array Except Self | 238. 除自身以外数组的乘积(Java)
  5. 首发!《长安十二时辰背后的技术秘籍》正式公开,速来下载
  6. (27)FPGA面试题动态时序模拟
  7. PHP中等良好优秀,成绩优秀,中等,良好怎么分的啊?分为哪几个?
  8. java split 坑
  9. Servlet技术 - Servlet应用
  10. 罗永浩发声:我的努力很可能失败 但好产品一定要赢
  11. Win11如何重置电脑 Win11重置电脑教程
  12. 个人财务管理系统设计与实现
  13. 使用include-what-you-use优化编译速度
  14. 配置web.xml文件时报The word ‘***‘ is not correctly spelled的解决方案
  15. 图片怎么转换为jpg格式的?照片如何在线转格式?
  16. [531]微信之wxpy库(基于itchat库)
  17. c语言0x前缀的作用,有趣的问题,C语言程序中,为什么十六进制数字以前缀0x开头呢?...
  18. FastDB 高效率的内存数据库系统
  19. 回归分析中的相关度(Corr)和R^2
  20. Python 数据结构 之 串 的链式存储结构

热门文章

  1. D. Ela and the Wiring Wizard floyd/思维
  2. 零基础CSS入门教程(8)–id选择器
  3. 机器学习(五)——时间序列ARIMA模型
  4. 一台服务器最大能支持多少条TCP连接
  5. Java常见面试题—final 在 java 中有什么作用?
  6. 【技术栈——00042】Docker网络端口指定的两种方式
  7. 安卓 linux it之家,IT之家安卓版 7.07:紧凑排版+适配华为小米魅族OV系统级推送等...
  8. 莫烦python神经网络进化(NeuroEvolution)之最全篇
  9. 什么是缓冲区溢出?有什么危害?其原因是什么?
  10. 量化投资中常遇到的两个问题