Qt網絡編程實現(xiàn)TCP通信
Qt網絡編程實現(xiàn)TCP通信,供大家參考,具體內容如下
標簽(空格分隔): Tcp通信
一、Tcp簡介
(1)TCP(Transmission Control Protocol,傳輸控制協(xié)議)TCP是一個用于數據傳輸的傳輸層網絡協(xié)議,多個網絡協(xié)議包括(HTTP和FTP都是基于TCP協(xié)議),TCP是面向數據流和連接的可靠的傳輸協(xié)議,它區(qū)別于傳輸層的另外一個協(xié)議UDP(具體可看—Qt簡單實現(xiàn)UDP通信) 。
(2)QTcpSocket繼承自QAbstractSocket,與QUdpSocket傳輸的數據報不同的是,QTcpSocket傳輸的是連續(xù)的數據流,尤其適合連續(xù)的數據傳輸,TCP一般分為客戶端和服務端,即C/S (Client/Server模型)。
(3)QTcpSocket代表了兩個獨立的數據流,一個用來讀取數據,一個用來寫入數據,分別采用QTcpSocket::read()及QTcpSocket::write()操作,讀取數據前先調用QTcpSocket::bytesAvailable來確定已有足夠的數據可用。QTcpServer處理客戶端的連接,可通過QTcpServer::listen()監(jiān)聽客戶端發(fā)來的連接請求,每當有客戶端連接時會發(fā)射newConnection()信號,QTcpSocket可用于讀取客戶端發(fā)來的數據報,亦可發(fā)送數據報。
二、傳輸層兩大協(xié)議Tcp\Udp的異同
三、小demo實現(xiàn)Tcp客戶端服務端通信
1、服務端:
新建Qt Widgets Application,用作tcp服務端,服務端任何時候只能被動等待連接,繼承自Qwidget類即可,設計ui界面,界面如下:
打開pro文件,添加支持網絡編程模塊,客戶端也需做如下修改:
添加tcp服務端m_tcpServer、tcp服務端套接字m_tcpSocket,在構造函數中監(jiān)聽客戶端的連接,樣例中服務端主要監(jiān)聽任何任何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(); ? ? ? //服務端讀取客戶端發(fā)來的數據 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); ? ? //服務端監(jiān)聽客戶端發(fā)來的請求 ? ? 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有數據時會發(fā)送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() { ? ? //服務端將客戶端發(fā)來的數據顯示到標簽上 ? ? QByteArray bt=m_tcpSocket->readAll(); ? ? ui->readLabel->setText(bt); }
2、客戶端
與服務端一樣,再新建Qt Widgets Application項目,用作tcp客戶端,繼承自Qwidget類即可,設計ui界面,界面如下:
添加客戶端tcp,在pro文件中添加網絡編程模塊network,給連接、發(fā)送按鈕添加點擊信號。
#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(); ?//點擊發(fā)送按鈕響應的槽函數 private: ? ? Ui::Widget *ui; ? ? QTcpSocket* m_tcpSocket; ? ?//tcp客戶端 }; #endif // WIDGET_H
構造函數中為服務端發(fā)來數據時觸發(fā)的readyRead信號添加了響應的槽函數onReadMessage,同時設置了客戶端連接時的默認ip地址和端口,onReadMessage槽函數將服務端反饋的數據顯示到標簽上,on_sendBtn_clicked槽函數中將行編輯框中的內容發(fā)送給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();//清空緩沖區(qū) }
四、運行結果
先打開服務端,再運行客戶端
客戶端采用默認ip和端口,這里的ip地址也可修改為其他,端口必須與服務端監(jiān)聽端口一致,點擊連接:
在行編輯框中隨便輸入內容,點擊發(fā)送:
ok達到目的!
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
詳解C++中賦值,關系,函數調用運算符重載的實現(xiàn)
本文主要為大家講解一下三個C++中的運算符重載,分別是賦值運算符重載、關系運算符重載和函數調用運算符重載,感興趣的小伙伴可以跟隨小編一起學習一下2022-06-06