網站首頁 編程語言 正文
Qt網絡編程實現TCP通信,供大家參考,具體內容如下
標簽(空格分隔): Tcp通信
一、Tcp簡介
(1)TCP(Transmission Control Protocol,傳輸控制協議)TCP是一個用于數據傳輸的傳輸層網絡協議,多個網絡協議包括(HTTP和FTP都是基于TCP協議),TCP是面向數據流和連接的可靠的傳輸協議,它區別于傳輸層的另外一個協議UDP(具體可看—Qt簡單實現UDP通信) 。
(2)QTcpSocket繼承自QAbstractSocket,與QUdpSocket傳輸的數據報不同的是,QTcpSocket傳輸的是連續的數據流,尤其適合連續的數據傳輸,TCP一般分為客戶端和服務端,即C/S (Client/Server模型)。
(3)QTcpSocket代表了兩個獨立的數據流,一個用來讀取數據,一個用來寫入數據,分別采用QTcpSocket::read()及QTcpSocket::write()操作,讀取數據前先調用QTcpSocket::bytesAvailable來確定已有足夠的數據可用。QTcpServer處理客戶端的連接,可通過QTcpServer::listen()監聽客戶端發來的連接請求,每當有客戶端連接時會發射newConnection()信號,QTcpSocket可用于讀取客戶端發來的數據報,亦可發送數據報。
二、傳輸層兩大協議Tcp\Udp的異同
三、小demo實現Tcp客戶端服務端通信
1、服務端:
新建Qt Widgets Application,用作tcp服務端,服務端任何時候只能被動等待連接,繼承自Qwidget類即可,設計ui界面,界面如下:
打開pro文件,添加支持網絡編程模塊,客戶端也需做如下修改:
添加tcp服務端m_tcpServer、tcp服務端套接字m_tcpSocket,在構造函數中監聽客戶端的連接,樣例中服務端主要監聽任何任何ip地址上的6666端口,并為客戶端連接時的newConnection信號添加相應的槽函數。
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
? ? Q_OBJECT
public:
? ? Widget(QWidget *parent = nullptr);
? ? ~Widget();
private slots:
? ? void onNewConnect(); ? ?//客戶端新的連接請求處理
? ? void onSendBackMsg(); ? //反饋信息給客戶端新的連接
? ? void onReadMsg(); ? ? ? //服務端讀取客戶端發來的數據
private:
? ? Ui::Widget *ui;
? ? QTcpServer* m_tcpServer; ? ?//tcp服務端
? ? QTcpSocket* m_tcpSocket; ? ?//tcp套接字
};
#endif // WIDGET_H
當服務端收到客戶端的連接時,服務端tcp反饋信息給客戶端,同時客戶端顯示的數據顯示到標簽上:
#include "widget.h"
#include "ui_widget.h"
#include <QTcpSocket>
Widget::Widget(QWidget *parent)
? ? : QWidget(parent)
? ? , ui(new Ui::Widget)
{
? ? ui->setupUi(this);
? ? m_tcpServer=new QTcpServer(this);
? ? //服務端監聽客戶端發來的請求
? ? if(!m_tcpServer->listen(QHostAddress::AnyIPv4,6666)){
? ? ? ? qDebug()<<m_tcpServer->errorString();
? ? ? ? close();
? ? }
? ? connect(m_tcpServer,&QTcpServer::newConnection,this,&Widget::onNewConnect);
? ? connect(m_tcpServer,&QTcpServer::newConnection,this,&Widget::onSendBackMsg);
}
Widget::~Widget()
{
? ? delete ui;
}
void Widget::onNewConnect()
{
? ? //當前連接的客戶端
? ? m_tcpSocket=m_tcpServer->nextPendingConnection();
? ? //斷開連接
? ? connect(m_tcpSocket,&QTcpSocket::disconnected,
? ? ? ? ? ? m_tcpSocket,&QTcpSocket::deleteLater);
? ? //socket有數據時會發送readyRead信號
? ? connect(m_tcpSocket,&QTcpSocket::readyRead,
? ? ? ? ? ? this,&Widget::onReadMsg);
}
void Widget::onSendBackMsg()
{
? ? QString str="你好,客戶端!";
? ? m_tcpSocket->write(str.toUtf8());
? ? ui->label->setText("反饋數據成功!");
}
void Widget::onReadMsg()
{
? ? //服務端將客戶端發來的數據顯示到標簽上
? ? QByteArray bt=m_tcpSocket->readAll();
? ? ui->readLabel->setText(bt);
}
2、客戶端
與服務端一樣,再新建Qt Widgets Application項目,用作tcp客戶端,繼承自Qwidget類即可,設計ui界面,界面如下:
添加客戶端tcp,在pro文件中添加網絡編程模塊network,給連接、發送按鈕添加點擊信號。
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
? ? Q_OBJECT
public:
? ? Widget(QWidget *parent = nullptr);
? ? ~Widget();
private slots:
? ? void onReadMessage(); ? //處理服務端反饋的數據
? ? void onDisplayError(QAbstractSocket::SocketError e); ? ?//打印錯誤信息
? ? void on_connectBtn_clicked(); ? //點擊連接按鈕響應信號的槽函數
? ? void on_sendBtn_clicked(); ?//點擊發送按鈕響應的槽函數
private:
? ? Ui::Widget *ui;
? ? QTcpSocket* m_tcpSocket; ? ?//tcp客戶端
};
#endif // WIDGET_H
構造函數中為服務端發來數據時觸發的readyRead信號添加了響應的槽函數onReadMessage,同時設置了客戶端連接時的默認ip地址和端口,onReadMessage槽函數將服務端反饋的數據顯示到標簽上,on_sendBtn_clicked槽函數中將行編輯框中的內容發送給tcp服務端。
#include "widget.h"
#include "ui_widget.h"
#include <QAbstractSocket>
const int gTcpPort=6666;
Widget::Widget(QWidget *parent)
? ? : QWidget(parent)
? ? , ui(new Ui::Widget)
{
? ? ui->setupUi(this);
? ? m_tcpSocket=new QTcpSocket(this);
? ? //socket有數據來了,做處理
? ? connect(m_tcpSocket,&QTcpSocket::readyRead,
? ? ? ? ? ? this,&Widget::onReadMessage);
? ? connect(m_tcpSocket,SIGNAL(QAbstractSocket::SocketError),
? ? ? ? ? ? this,SLOT(onDisplayError(QAbstractSocket::SocketError)));
? ? //設置客戶端連接默認的主機地址及端口號
? ? ui->hostLineEdit->setText("127.0.0.1");
? ? ui->portLineEdit->setText(QString::number(gTcpPort));
}
Widget::~Widget()
{
? ? delete ui;
}
void Widget::onReadMessage()
{
? ? QByteArray bt;
? ? bt.resize(m_tcpSocket->bytesAvailable());
? ? m_tcpSocket->read(bt.data(),bt.size());
? ? //將客戶端反饋的數據顯示到標簽上
? ? ui->recvLabel->setText(bt);
}
void Widget::onDisplayError(QAbstractSocket::SocketError e)
{
? ? qDebug()<<"SocketError:"<<e<<endl
? ? ? ? ? ?<<m_tcpSocket->errorString();
}
void Widget::on_connectBtn_clicked()
{
? ? m_tcpSocket->abort();
? ? //連接服務端
? ? m_tcpSocket->connectToHost(ui->hostLineEdit->text(),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ui->portLineEdit->text().toInt());
}
void Widget::on_sendBtn_clicked()
{
? ? m_tcpSocket->write(ui->sendEdit->text().toUtf8());
? ? m_tcpSocket->flush();//清空緩沖區
}
四、運行結果
先打開服務端,再運行客戶端
客戶端采用默認ip和端口,這里的ip地址也可修改為其他,端口必須與服務端監聽端口一致,點擊連接:
在行編輯框中隨便輸入內容,點擊發送:
ok達到目的!
原文鏈接:https://blog.csdn.net/qq_43686329/article/details/120358274
相關推薦
- 2023-11-15 LaTeX調整圖片大小的方法;自動調整合適的大小
- 2023-10-16 Nginx啟動,重啟以及基本命令
- 2022-02-24 Matlab中plot函數及legend函數詳解
- 2022-09-04 Python?Matplotlib繪制箱線圖boxplot()函數詳解_python
- 2022-07-18 python中數組array和列表list的基本用法及區別解析_python
- 2022-03-31 解決Android加殼過程中mprotect調用失敗的原因分析_Android
- 2023-01-12 React?useCallback鉤子的作用方法demo_React
- 2022-07-19 AI與Python人工智能啟發式搜索概念理解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支