Qt 網絡編程

QT 網絡編程

TCP 編程

模塊引入

QT += network

在這里插入圖片描述

頭文件

#include <QTcpServer> // TCP服務器端使用
#include <QTcpSocket> // TCP服務器和客戶端都使用

編程流程

服務端

1)實例化 QTcpServer 對象 -----------------------------> socket
2)進入監聽狀態 ----> listen(QTcpServer類) // 不需要再綁定了----------->bind + listen
3)監測客戶端連接 ---- newConnection 信號(QTcpServer類)
----------------> 有新連接過來,server 就能收到 newConnection 信號
4)QTcpSocket *client <---- 獲得連接 ---- nextPendingConnection(QTcpServer類) ---->accept
5)連接對端接收信號 ------ readyRead(QTcpSocket類)
---------------------->如果對端有數據發送,server 就能收到 readyRead 信號
6)讀取客戶端消息 ------ readAll(QTcpSocket類) --------------------------> recv:讀取數據
7)發送數據 ------ write(QTcpSocket類) ----> send:發數據
8)關閉連接 ------ disconnectFromHost() -------------------> close
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

客戶端

1)實例化 QTcpSocket 對象;
2)連接服務器 ------ connectToHost ------> 接下來使用 waitForConnected 來判斷是否連接成功
3)連接對端接收信號 ------ readyRead 信號
4)發送數據 ------ write()
5)關閉連接 ------ disconnectFromHost()
在這里插入圖片描述
在這里插入圖片描述

💡 客戶端實現

widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QtWidgets>
#include <QTcpSocket>namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private slots:void on_connectBtn_clicked();void recvSlot();void on_sendBtn_clicked();
//    void whetherConnectedSlot();		// 判斷是否連接成功,方法二private:Ui::Widget *ui;QTcpSocket *client;bool flag;
};#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("客戶端");client = new QTcpSocket(this);QObject::connect(client, SIGNAL(readyRead()), this,  SLOT(recvSlot()));// 判斷是否連接成功,方法二
//    QObject::connect(client, SIGNAL(connected()), this,  SLOT(whetherConnectedSlot()));
}Widget::~Widget()
{delete ui;
}// void Widget::whetherConnectedSlot()			// 判斷是否連接成功,方法二
// {
//     flag = true;
// }void Widget::on_connectBtn_clicked()
{client->connectToHost(ui->ipEdit->text(), ui->portEdit->text().toShort());// 判斷是否連接成功,方法一if (!client->waitForConnected(1000))           {qDebug() << "Failed to connect. ";return ;}qDebug() << "Connected successfully! ";ui->connectBtn->setText("斷開");
}void Widget::recvSlot()
{QByteArray buffer = client->readAll();ui->recvEdit->setText(QString::fromLocal8Bit(buffer));
}void Widget::on_sendBtn_clicked()
{QString buffer = ui->sendEdit->toPlainText();client->write(buffer.toLocal8Bit());
}

在這里插入圖片描述

💡 服務器實現

widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QtWidgets>
#include <QTcpServer>
#include <QTcpSocket>namespace Ui {
class Widget;
}class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = 0);~Widget();private slots:void on_connectBtn_clicked();void connectSlot();void recvSlot();void on_sendBtn_clicked();private:Ui::Widget *ui;QTcpServer *server;QTcpSocket *client;
};#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);server = new QTcpServer(this);this->setWindowTitle("服務器");// 這個信號觸發,代表有客戶端連接QObject::connect(server, SIGNAL(newConnection()), this,  SLOT(connectSlot()));
}Widget::~Widget()
{delete ui;
}void Widget::on_connectBtn_clicked()
{// 監聽是否有客戶端連入,不阻塞等待if (!server->listen(QHostAddress::Any, ui->portEdit->text().toUShort())){qDebug() << "Failed to listen. ";return ;}ui->connectBtn->setText("關閉");
}void Widget::connectSlot()
{// 接受新的客戶端連接client = server->nextPendingConnection();if (client == 0){qDebug() << "There are no pending connections. ";return ;}// 一定要等到接受連接后,再去做客戶端的信號連接QObject::connect(client, SIGNAL(readyRead()), this,  SLOT(recvSlot()));
}void Widget::recvSlot()
{QByteArray buffer = client->readAll();// 編碼轉換:對方必須按照 GBK 格式發送ui->recvEdit->setText(QString::fromLocal8Bit(buffer));
}void Widget::on_sendBtn_clicked()
{QString buffer = ui->sendEdit->toPlainText();	// 從textEdit中獲取的內容一定是utf8編碼client->write(buffer.toLocal8Bit());
}

在這里插入圖片描述

💡 服務器與客戶端交互

在這里插入圖片描述

UDP 編程

模塊引入

QT += network

在這里插入圖片描述

頭文件

#include

編程流程

1)實例化 QUdpSocket 對象 ------------------------------------------> socket
2)綁定地址、端口 ------ bind(QHostAddress::LocalHost,8888) -----> bind
3)收發報文 ------ readDatagram、writeDatagram ------------------> recvfrom/sendto
在這里插入圖片描述

// 類和接口
bool 	QUdpSocket::hasPendingDatagrams() const;
qint64 	QUdpSocket::readDatagram(char * data, qint64 maxSize, QHostAddress * address = 0, quint16 * port = 0);
qint64 	QUdpSocket::writeDatagram(const char * data, qint64 size, const QHostAddress & address, quint16 port);

實現一個聊天功能,使用 UDP 通信。首先通過一個登錄界面,輸入服務器的 IP 和端口,點擊登錄后,將 IP 和端口傳到聊天界面,然后通過 UDP 進行聊天(服務器)。

💡 服務器實現

在這里插入圖片描述

chatpage.h
#ifndef CHATPAGE_H
#define CHATPAGE_H#include <QtWidgets>
#include <QUdpSocket>
#include "globalvalue.h"namespace Ui {
class ChatPage;
}class ChatPage : public QWidget
{Q_OBJECTpublic:explicit ChatPage(QWidget *parent = 0);~ChatPage();private:Ui::ChatPage *ui;QUdpSocket *socket;QHostAddress sender;        // 定義對端的地址,以便后續發送使用quint16 senderPort;private slots:void readPendingDatagrams();void on_sendBtn_clicked();
};#endif // CHATPAGE_H
chatpage.cpp
#include "chatpage.h"
#include "ui_chatpage.h"ChatPage::ChatPage(QWidget *parent) :QWidget(parent),ui(new Ui::ChatPage)
{ui->setupUi(this);this->setWindowTitle("聊天");// 初始化一個 QUdpSocket 對象socket = new QUdpSocket(this);// 綁定服務器的地址和IP,客戶端省略此句socket->bind(QHostAddress(GlobalValue::ipaddr), GlobalValue::port);connect(socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
}ChatPage::~ChatPage()
{delete ui;
}void ChatPage::readPendingDatagrams()
{// 如果udp緩沖區有報文數據的話while (socket->hasPendingDatagrams()){QByteArray datagram;    // 初始化一個字節流緩沖區datagram.resize(socket->pendingDatagramSize());		// 重設緩沖區的大小socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);// 對方發送的字節流必須是GBK編碼ui->recvEdit->setText(QString::fromLocal8Bit(datagram));}
}
void ChatPage::on_sendBtn_clicked()
{// 如果已經接收過消息,那么sender和senderPort已經有對方的地址了socket->writeDatagram(ui->sendEdit->toPlainText().toLocal8Bit(), sender, senderPort);
}

在這里插入圖片描述

globalvalue.h
#ifndef GLOBALVALUE_H
#define GLOBALVALUE_H#include <QString>class GlobalValue           // 此類僅用于存放靜態變量
{
public:GlobalValue();static QString ipaddr;static quint16 port;
};#endif // GLOBALVALUE_H
globalvalue.cpp
#include "globalvalue.h"QString GlobalValue::ipaddr;
quint16 GlobalValue::port;GlobalValue::GlobalValue()
{
}
userver.h
#ifndef USERVER_H
#define USERVER_H#include <QtWidgets>
#include "chatpage.h"
#include "globalvalue.h"namespace Ui {
class UServer;
}class UServer : public QWidget
{Q_OBJECTpublic:explicit UServer(QWidget *parent = 0);~UServer();private slots:void on_pushButton_clicked();private:Ui::UServer *ui;ChatPage *chatting;
};#endif // USERVER_H
userver.cpp
#include "userver.h"
#include "ui_userver.h"UServer::UServer(QWidget *parent) :QWidget(parent),ui(new Ui::UServer)
{ui->setupUi(this);this->setWindowTitle("登錄");
}UServer::~UServer()
{delete ui;
}void UServer::on_pushButton_clicked()
{GlobalValue::ipaddr = ui->ipEdit->text();GlobalValue::port = ui->portEdit->text().toUShort();chatting = new ChatPage;chatting->show();   // 初始化一個新的界面,然后進行跳轉this->close();
}

運行效果如下:
在這里插入圖片描述
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/283812.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/283812.shtml
英文地址,請注明出處:http://en.pswp.cn/news/283812.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HDU 5037 Frog(2014年北京網絡賽 F 貪心)

開始就覺得有思路&#xff0c;結果越敲越麻煩。。。   題意很簡單&#xff0c;就是說一個青蛙從0點跳到m點&#xff0c;最多可以跳l的長度&#xff0c;原有石頭n個&#xff08;都僅表示一個點&#xff09;。但是可能跳不過去&#xff0c;所以你是上帝&#xff0c;可以隨便在哪…

Kafka高性能高吞吐的原因總結

1、磁盤順序讀寫 保證了消息的堆積 順序讀寫 磁盤會預讀,預讀即在讀取的起始地址連續讀取多個頁面&#xff0c;主要時間花費在了傳輸時間,而這個時間兩種讀寫可以認為是一樣的。 隨機讀寫 因為數據沒有在一起&#xff0c;將預讀浪費掉了&#xff0c;需要多次尋道和旋…

日利率

2019獨角獸企業重金招聘Python工程師標準>>> 利率計算 轉載于:https://my.oschina.net/u/3342652/blog/1649028

linux下使用tar命令

解壓語法&#xff1a;tar [主選項輔選項] 文件或者目錄 使用該命令時&#xff0c;主選項是必須要有的&#xff0c;它告訴tar要做什么事情&#xff0c;輔選項是輔助使用的&#xff0c;可以選用。主選項&#xff1a;c 創建新的檔案文件。如果用戶想備份一個目錄或是一些文件&…

Kafka 安裝詳解

注意&#xff1a;確保有JDK1.8版本及以上 官方文檔&#xff1a;https://kafka.apache.org/quickstart 清華鏡像下載&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/ 首先下載安裝包&#xff0c;在linux及Windows都可以使用。 1. Centos 安裝部署 1.1 下載 將下…

【Maui正式版】創建可跨平臺的Maui程序,以及有關依賴注入、MVVM雙向綁定的實現和演示...

前言&#xff1a;Maui終于在2022年8月9日推送出來了。今兒就迫不及待來把玩一下先。A、我本地已有VS2022&#xff0c;不過版本比較老&#xff0c;此處選擇更新。工具 -> 獲取功能和更新里面&#xff0c;可以獲取到新版本更新。B、最新版本是17.3.0&#xff0c;我本地只有17.…

學go語言能做什么工作?

Go語言主要用作服務器端開發&#xff0c;其定位是用來開發“大型軟件”的&#xff0c;適合于很多程序員一起開發大型軟件&#xff0c;并且開發周期長&#xff0c;支持云計算的網絡服務。Go語言能夠讓程序員快速開發&#xff0c;并且在軟件不斷的增長過程中&#xff0c;它能讓程…

WebSQL存儲

2019獨角獸企業重金招聘Python工程師標準>>> WebSQL這種存儲技術&#xff0c;相對于學過數據庫的人來說&#xff0c;還是比較容易理解和上手的&#xff0c;主要就是它的存儲風格和我們一般所學的SQL Server 和Oracle比較像&#xff0c;對于HTML5來說&#xff0c;當然…

軟件工程第一次作業補充

1.關注《構建之法》的作者鄒欣老師的博客&#xff1b;2.花二十分鐘寫一個能自動生成小學四則運算題目的“軟件”&#xff0c;要求除了整數以外&#xff0c;還要支持真分數的四則運算。將代碼上傳至coding.net,并將地址發布至自己的博客。代碼地址&#xff1a; https://coding.n…

抖音服務器帶寬有多大,才能供上億人同時刷?

最近看到一個有意思的提問&#xff1a;抖音服務器帶寬有多大&#xff0c;為什么能夠供那么多人同時刷&#xff1f;今天來給小伙伴們科普一下。 抖音&#xff0c;百度&#xff0c;阿里云&#xff0c;騰訊都是自建的數據中心&#xff0c;都是 T 級別出口帶寬&#xff08;總出口帶…

ASP.NET Core 5.0中的Host.CreateDefaultBuilder執行過程

通過Rider調試的方式看了下ASP.NET Core 5.0的Web API默認項目&#xff0c;重點關注Host.CreateDefaultBuilder(args)中的執行過程&#xff0c;主要包括主機配置、應用程序配置、日志配置和依賴注入配置這4個部分。由于水平和篇幅有限&#xff0c;先整體理解、建立框架&#xf…

404和302

為什么80%的碼農都做不了架構師&#xff1f;>>> 404 php中用header()函數是可以為返回頁面添加404的頭信息的&#xff0c;從而提示瀏覽器該網頁找不到了。 所以可以使用&#xff1a;header("HTTP/1.0 404 Not Found");或者&#xff1a;header("Stat…

oracle sqlplus使用

2019獨角獸企業重金招聘Python工程師標準>>> 1、常用連接方式 sqlplus / as sysdba 無需數據庫進入可用狀態&#xff0c;就可用用該命令登錄&#xff0c;運行startup來啟動。 sqlplus username/pwdhost/service_name&#xff0c;如&#xff1a; sqlplus tiger/scott…

20款IDEA 神級插件 效率提升 30 倍,寫代碼必備

插件目錄 1. Alibaba Java Coding Guidelines 2.GsonFormat 3.A8Translation 4.Maven Helper 5.Free Mybatis plugin 6.Grep Console 7.Lombok 8.Nyan progress bar 9.FindBugs-IDEA 10.Key Promoter X 11.JavaDoc 12.ignore 13.RainbowBrackets 14.Activate-power-mode 15.C…

【溫故知新】C# Linq中 Where使用技巧

微信公眾號&#xff1a;趣編程ACE關注可了解更多的.NET日常實戰開發技巧&#xff0c;如需源碼 后臺回復 源碼 即可;如果覺得對你有幫助&#xff0c;歡迎關注C# Linq中 Where使用技巧hello 大家好&#xff0c;很開心又能重新分享C#編程開發技巧了&#xff0c;之前因為工作和生活…

JS引用類型 -- Array類型

ECMAScript數組與其他語言中的數組都是數據的有序列表&#xff0c;但與其他語言不同的是&#xff0c;ECMAScript數組的每一項可以保存任何類型的數據。而且ECMAScript數組的大小是可以動態調整的&#xff0c;即可以隨著數據的添加自動增長。 創建數組的基本方式有兩種&#xff…

分布式id解決方案

文章目錄 1.分布式id實現方案 1.1.uuid1.2 數據庫主鍵自增1.3 Redis自增1.4 號段模式1.5 雪花算法&#xff08;snowflake&#xff09; 1.5.1 百度&#xff08;uid-generator&#xff09;1.5.2 美團&#xff08;Leaf&#xff09;所謂id就是能夠用作唯一標識的記號。 在我們日常的…

我和大象的十年往事 - 感恩、感謝、加油、騰飛

背景 http://www.idcquan.com/Special/OSCAR2018/index.html 由中國信息通信研究院主辦、中國通信標準化協會支持的"OSCAR云計算開源產業大會"于2018年3月21日&#xff0d;22日在國家會議中心舉行。 非常有幸獲得了“OSCAR尖峰開源人物”獎項。 獎項不敢自居&#xf…

Httpclient發送json請求

一、Httpclient發送json請求 public String RequestJsonPost(String url){ String strresponse null; try{ HttpClient hc new DefaultHttpClient(); HttpPost hp new HttpPost(url); JSONObject jsonParam new JSONObject(); jsonParam.pu…

基于ABP的AppUser對象擴展

在ABP中AppUser表的數據字段是有限的&#xff0c;現在有個場景是和小程序對接&#xff0c;需要在AppUser表中添加一個OpenId字段。今天有個小伙伴在群中遇到的問題是基于ABP的AppUser對象擴展后&#xff0c;用戶查詢是沒有問題的&#xff0c;但是增加和更新就會報"XXX fie…