QT TCP網絡通信編程

學習目標:?TCP網絡通信編程

前置環境

運行環境:qt?creator 4.12

學習內容

一、TCP 協議基礎知識:

  1. TCP 是一種面向連接的、可靠的、基于字節流的傳輸層通信協議。
  2. TCP 擁塞控制算法包括慢啟動、擁塞避免、快速重傳和快速恢復。
  3. TCP 通信需要建立連接,Qt 提供 QTcpSocket 和 QTcpServer 類用于 TCP 客戶端和服務器編程。
  4. QTcpServer 類用于建立網絡監聽和 socket 連接,主要接口函數如 listen()、newConnection() 等。

QTcpServer* tcpServer; 它負責監聽指定的 IP 地址和端口,并在有新的客戶端連接時發出 newConnection() 信號。

QTcpSocket* tcpSocket; 它代表一個與服務端建立的 TCP 連接。

QTcpServer類

QTcpServer 是 Qt 框架提供的 TCP 服務器類,它提供了一系列常用的成員函數和信號,用于實現 TCP 服務器的基本功能。以下是 QTcpServer 的一些常用成員函數:

  1. 構造函數和析構函數:

    • QTcpServer(QObject *parent = nullptr):創建一個 QTcpServer 對象。
    • ~QTcpServer():析構函數,用于釋放資源。
  2. 服務器狀態控制:

    • bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0):開始監聽指定的地址和端口。
    • void close():停止監聽并關閉服務器。
      • abort()是強行立即關閉連接,相當于調用disconnectFromHost()。關閉后會釋放所有相關資源并觸發 QAbstractSocket::abort信號。對端可能不知道連接已經關閉。

      • close()是通過標準關閉序列完成關閉,等待對端確認,保證數據完整性。它會優雅地關閉socket連接,先發送關閉請求給對端,并等待對端確認。然后會進入關閉狀態,觸發QAbstractSocket::stateChanged(QAbstractSocket::ClosingState)和QAbstractSocket::disconnected信號。

    • bool isListening() const:檢查服務器是否正在監聽。
  3. 獲取服務器信息:

    • QHostAddress serverAddress() const:返回服務器綁定的地址。
    • quint16 serverPort() const:返回服務器綁定的端口。
    • QAbstractSocket::SocketError socketError() const:返回最近一次發生的套接字錯誤。
    • QString errorString() const:返回最近一次發生的錯誤的描述字符串。
  4. 新連接管理:

    • QTcpSocket *nextPendingConnection():返回下一個待處理的連接。
    • int hasPendingConnections() const:返回待處理連接的數量。
  5. 信號處理:

    • void newConnection():當有新的連接到達時發出此信號。
    • void acceptError(QAbstractSocket::SocketError socketError):當接受新連接時發生錯誤時發出此信號。
  6. 其他功能:

    • void setMaxPendingConnections(int numConnections):設置服務器可以同時處理的最大待處理連接數。
    • int maxPendingConnections() const:返回服務器的最大待處理連接數。
    • void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value):設置套接字選項。
    • QVariant socketOption(QAbstractSocket::SocketOption option) const:獲取套接字選項的當前值。
  7. 地址和端口設置:

    • void setAddress(const QHostAddress &address):設置服務器監聽的地址。
    • QHostAddress address() const:返回服務器監聽的地址。
    • void setPort(quint16 port):設置服務器監聽的端口。
    • quint16 port() const:返回服務器監聽的端口。
  8. SSL/TLS 支持:

    • void setSecureMode(QSsl::SslMode mode):設置服務器的 SSL/TLS 模式。
    • QSsl::SslMode secureMode() const:返回服務器的 SSL/TLS 模式。
    • void setLocalCertificate(const QSslCertificate &certificate):設置服務器的本地證書。
    • QSslCertificate localCertificate() const:返回服務器的本地證書。
    • void setPrivateKey(const QSslKey &key):設置服務器的私鑰。
    • QSslKey privateKey() const:返回服務器的私鑰。
  9. 線程安全:

    • void setThreadPool(QThreadPool *threadPool):設置用于處理新連接的線程池。
    • QThreadPool *threadPool() const:返回用于處理新連接的線程池。
  10. 日志記錄:

    • void setProxy(const QNetworkProxy &proxy):設置代理服務器。
    • QNetworkProxy proxy() const:返回當前使用的代理服務器。

這些成員函數提供了更多的靈活性和控制能力,使開發者能夠根據具體需求配置和管理 TCP 服務器。例如,可以設置 SSL/TLS 模式以提供安全的通信,使用線程池來提高并發處理能力,以及設置代理服務器以實現更復雜的網絡拓撲。

QTcpServer?類的使用:

  • QTcpServer?是從?QObject?繼承的類,用于服務器建立網絡監聽和創建網絡 socket 連接。
  • 主要接口函數包括?listen()nextPendingConnection()serverAddress()?和?serverPort()?等。

服務器Server提供的回調函數

在 Qt TCP 編程中,主要提供了以下幾種重要的回調接口:

  1. QTcpServer?相關的回調:

    • QTcpServer::newConnection(): 當有新的客戶端連接到達時觸發該信號。
    • QTcpServer::acceptError(QAbstractSocket::SocketError socketError): 當服務器無法接受新的連接時觸發該信號,可以獲取錯誤信息。
  2. QTcpSocket?相關的回調:

    • QTcpSocket::connected(): 當套接字成功連接到遠程主機時觸發該信號。
    • QTcpSocket::disconnected(): 當套接字斷開連接fin 位 為1時觸發該信號。
    • QTcpSocket::readyRead(): 當套接字有新數據可讀時觸發該信號。
    • QTcpSocket::bytesWritten(qint64 bytes): 當成功寫入數據到套接字時觸發該信號,并返回寫入的字節數。
    • QTcpSocket::error(QAbstractSocket::SocketError socketError): 當套接字發生錯誤時觸發該信號,可以獲取錯誤信息。
    • QTcpSocket::stateChanged(QAbstractSocket::SocketState socketState): 當套接字的連接狀態發生變化時觸發該信號。
    • bytesWritten(qint64 bytes)?信號:

      • 當成功寫入數據到?QTcpSocket?時會觸發此信號。
      • bytes?參數表示成功寫入的字節數。
      • 可以用來監控數據發送的進度。
    • aboutToClose()?信號:

      • 當?QTcpSocket?將要關閉時會觸發此信號。
      • 可以在此信號的槽函數中執行一些數據刷新或保存操作。
    • hostFound()?信號:

      • 當?QTcpSocket?成功解析了主機地址時會觸發此信號。
      • 可以用來監控 DNS 解析的進度。
  3. QSslSocket?相關的回調(用于 SSL/TLS 連接):

    • QSslSocket::sslErrors(const QList<QSslError> &errors): 當 SSL/TLS 連接發生錯誤時觸發該信號。
    • QSslSocket::encrypted(): 當 SSL/TLS 連接成功加密時觸發該信號。
  4. QNetworkProxy?相關的回調:

    • QTcpSocket::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator): 當需要代理服務器認證時觸發該信號。

這些回調接口涵蓋了 TCP 連接的整個生命周期,包括連接建立、數據交互、連接斷開以及各種錯誤情況。通過監聽和處理這些信號,我們可以更好地控制和管理 TCP 連接,提高應用程序的可靠性和健壯性。

QT TCP網絡通信編程項目

本地聊天傳輸,項目效果:

TCP服務端代碼

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);setWindowTitle("TCP通訊服務端");//獲取主機名和ip地址QHostInfo info =QHostInfo::fromName(QHostInfo::localHostName());QList<QHostAddress> addrs=info.addresses();if(!addrs.empty()){foreach(const QHostAddress & addr,addrs){if(addr.protocol()==QAbstractSocket::IPv4Protocol){ui->serverip->addItem(addr.toString());}}}tcpServer=new QTcpServer(this);//注冊新連接回調 表示有新的客戶端連接到達服務器。connect(tcpServer,&QTcpServer::newConnection,this,&MainWindow::ConnectCallback);}void MainWindow::ConnectCallback(){ //連接到達tcpSocket = tcpServer->nextPendingConnection();//連接成功后回調 表示當前 TCP 連接已經成功建立。auto clientconnect=[this](){// 客戶端連接ui->plainTextEdit->appendPlainText("**********客戶端socket連接成功**********");ui->plainTextEdit->appendPlainText("**********peer address:"+tcpSocket->peerAddress().toString());ui->plainTextEdit->appendPlainText("**********peer port:"+QString::number(tcpSocket->peerPort()));};connect(tcpSocket,&QTcpSocket::connected,this,clientconnect);clientconnect(); //因為當前連接已經到達了 所有手動調用一次//讀前回調 當 tcpSocket 有數據可讀時,該信號會被觸發connect(tcpSocket,&QTcpSocket::readyRead,this,[this](){while(tcpSocket->canReadLine()){QString result = "ip:%1 prot:%2 in:%3 ";result = result.arg(tcpSocket->peerAddress().toString()).arg(QString::number(tcpSocket->peerPort())).arg(QString(tcpSocket->readLine()));ui->plainTextEdit->appendPlainText(result);}});//錯誤回調  當 tcpSocket 發生錯誤時,該信號會被觸發connect(tcpSocket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error),this, [this](QAbstractSocket::SocketError error) {// ui->plainTextEdit->appendPlainText("Socket error:" + error + tcpSocket->errorString());});//當套接字的連接狀態發生變化時,該信號會被觸發,并且會傳遞一個 QAbstractSocket::SocketState 類型的參數,表示當前的連接狀態。connect(tcpSocket,QOverload<QAbstractSocket::SocketState>::of(&QTcpSocket::stateChanged),this,[this](QTcpSocket::SocketState state){// ui->plainTextEdit->appendPlainText("套接字狀態變更:" + state);});//斷開連接 fin位確認 回調connect(tcpSocket,&QTcpSocket::disconnected,this,[this](){// 客戶端斷開連接QString result = "**********客戶端socket斷開連接[ip:%1,prot:%2,]";result = result.arg(tcpSocket->peerAddress().toString()).arg(QString::number(tcpSocket->peerPort()));ui->plainTextEdit->appendPlainText(result);tcpSocket->deleteLater();});
}
MainWindow::~MainWindow()
{delete ui;if(tcpServer->isListening()){// 關閉TCP服務器tcpServer->close();tcpServer->deleteLater(); //最終關閉qDebug() << "TCP server MainWindow.";}
}
void MainWindow::closeEvent(QCloseEvent *e){ //關閉窗口//關閉closeMainWindow::on_stopServer_clicked();e->accept(); //允許窗口完成關閉操作。
}void MainWindow::on_startServer_clicked()
{QString ip(ui->serverip->currentText());uint16_t port =ui->serverport->value();tcpServer->listen(QHostAddress(ip),port);ui->plainTextEdit->appendPlainText("$$$$$$$$$$開始監聽$$$$$$$$$$");ui->plainTextEdit->appendPlainText("服務器地址:"+tcpServer->serverAddress().toString());ui->plainTextEdit->appendPlainText("服務器端口:"+QString::number(tcpServer->serverPort()));ui->startServer->setEnabled(false);ui->stopServer->setEnabled(true);}void MainWindow::on_stopServer_clicked() //關閉tcpserver
{//先關閉所有socketif(!tcpSocket){tcpSocket->disconnect(); //用于斷開 QTcpSocket 對象的所有信號與槽的連接。tcpSocket->close();      //它會向對端發送 FIN 數據包,并等待對端的確認,完成 TCP 連接的正常關閉過程。//fin回調 已調用 tcpSocket->deleteLater(); //它不會立即刪除對象,而是將其標記為待刪除狀態,等到當前事件循環結束后再執行刪除操作。}if(tcpServer->isListening()){tcpServer->close();//不調用 deleteLater 為了下次再次開啟ui->startServer->setEnabled(true);ui->stopServer->setEnabled(false);ui->plainTextEdit->clear();}}void MainWindow::on_sendmsg_clicked()
{QString msg =ui->lineEdit->text();ui->lineEdit->clear();ui->plainTextEdit->appendPlainText("[out]:"+msg);tcpSocket->write(msg.toUtf8()+'\n');}

TCP客戶端代碼

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);setWindowTitle("tcp通信客戶端");QHostInfo info =QHostInfo::fromName(QHostInfo::localHostName());QList<QHostAddress> addrs =info.addresses();if(!addrs.empty()){foreach(const QHostAddress& addr ,addrs){if(addr.protocol() == QAbstractSocket::IPv4Protocol){ui->serverip->addItem(addr.toString());}}}client = new QTcpSocket();//當 socket 成功連接到服務器時,會發射 connected() 信號。connect(client,&QTcpSocket::connected,this,[this](){ui->plainTextEdit->appendPlainText("**********已經連接到服務器端**********");ui->plainTextEdit->appendPlainText("服務器端ip:"+client->peerAddress().toString());ui->plainTextEdit->appendPlainText("服務器端port:"+QString::number(client->peerPort()));ui->tcpconnect->setEnabled(false);ui->tcpclose->setEnabled(true);});//當 socket 與服務器斷開連接時,會發射 disconnected() 信號。connect(client,&QTcpSocket::disconnected,this,[this](){ui->plainTextEdit->appendPlainText("**********已斷開與服務器端的連接**********");client->close();ui->tcpconnect->setEnabled(true);ui->tcpclose->setEnabled(false);});//當 socket 有新的數據可讀時,會發射 readyRead() 信號。connect(client,&QTcpSocket::readyRead,this,[this](){while(client->canReadLine()){ui->plainTextEdit->appendPlainText("[in]:"+client->readLine());}});}MainWindow::~MainWindow()
{delete ui;
}\void MainWindow::on_send_clicked()
{QString msg=ui->lineEdit->text();ui->plainTextEdit->appendPlainText("[out]:"+msg);ui->lineEdit->clear();client->write(msg.toUtf8()+'\n');}void MainWindow::on_tcpconnect_clicked()
{QString ip=ui->serverip->currentText();quint16 port =ui->serverport->value();client->connectToHost(ip,port);if (!client->waitForConnected(3000)) {// 5s 連接超時處理邏輯ui->plainTextEdit->appendPlainText("連接超時,請檢查服務器ip和port是否正確.");}}void MainWindow::on_tcpclose_clicked()
{if(client->state() ==QAbstractSocket::ConnectedState) client->disconnectFromHost(); //這里首先檢查 tcpclient 對象的當前連接狀態。ui->tcpconnect->setEnabled(true);ui->tcpclose->setEnabled(false);}
// 在應用程序退出或客戶端斷開連接時 點關閉窗口
void MainWindow::closeEvent(QCloseEvent* event) {// 1. 斷開與服務器的連接if (client->state() == QAbstractSocket::ConnectedState) {client->disconnectFromHost();}qDebug()<<"closeEvent";// 2. 釋放 QTcpSocket 對象client->deleteLater();// 允許窗口關閉event->accept();
}

?總結

server端

  1. TCP 服務器的創建和啟停:

    • 在構造函數中創建?QTcpServer?對象,并連接?newConnection()?信號到?ConnectCallback?函數。
    • on_startServer_clicked()?函數中,監聽指定的 IP 和端口,啟動 TCP 服務器。
    • on_stopServer_clicked()?函數中,關閉 TCP 服務器,斷開所有客戶端連接。
    • 在主窗口關閉時,調用?on_stopServer_clicked()?函數關閉服務器。
  2. 客戶端連接的處理:

    • 在?ConnectCallback?函數中,獲取新連接的?QTcpSocket?對象。
    • 連接客戶端連接成功、數據可讀、錯誤、狀態變更、斷開連接等信號。
    • 在信號處理函數中,輸出連接信息并處理數據收發。
  3. 數據收發和協議處理:

    • 連接?readyRead()?信號,處理客戶端發送的數據。
    • 使用?tcpSocket->readLine()?讀取并解析數據,輸出到 UI 界面。
    • on_sendmsg_clicked()?函數中,通過?tcpSocket->write()?將消息發送給客戶端。
  4. 異常處理:

    • 連接?error()?信號,處理套接字錯誤。
    • 連接?stateChanged()?信號,監控連接狀態變更。
  5. 生命周期管理:

    • 在主窗口析構函數中,關閉 TCP 服務器并釋放資源。
    • 在客戶端斷開連接時,釋放?QTcpSocket?對象。
      • 如果需要立即關閉連接而不管數據完整性,使用abort()。

      • 如果需要負責任關閉保證數據完整,則使用close()。

通過學習這段代碼,我們可以掌握以下 Qt TCP 編程的關鍵點:

  1. 如何創建 TCP 服務器并監聽端口。
  2. 如何處理新的客戶端連接,并與之進行數據通信。
  3. 如何處理連接錯誤和狀態變更。
  4. 如何優雅地關閉服務器并釋放資源。

客戶端

  1. TCP 客戶端的創建和連接:

    • 在構造函數中創建?QTcpSocket?對象?client
    • 連接?connected()?信號,處理與服務器成功連接的情況。
    • on_tcpconnect_clicked()?函數中,調用?connectToHost()?連接到服務器。
    • 使用?waitForConnected()?處理連接超時的情況。
  2. 數據收發和協議處理:

    • 連接?readyRead()?信號,處理服務器發送的數據。
    • 使用?client->readLine()?讀取并解析數據,輸出到 UI 界面。
    • on_send_clicked()?函數中,通過?client->write()?將消息發送給服務器。
  3. 連接狀態管理:

    • 連接?disconnected()?信號,處理與服務器的斷開連接。
    • 在?closeEvent()?中,檢查連接狀態并斷開連接。
    • 更新 UI 按鈕的狀態,反映當前的連接狀態。
  4. 異常處理:

    • 在連接超時的情況下,輸出錯誤提示信息。
    • 在?closeEvent()?中,釋放?QTcpSocket?對象。

通過學習這段代碼,我們可以掌握以下 Qt TCP 客戶端編程的關鍵點:

  1. 如何創建 TCP 客戶端并連接到服務器。
  2. 如何處理數據的收發,并按照約定的協議進行解析。
  3. 如何管理連接狀態,處理連接成功、斷開等情況。
  4. 如何優雅地關閉連接并釋放資源。

? ??

最后附上源代碼鏈接
對您有幫助的話,幫忙點個star

35-tcpSocket-client · jbjnb/Qt demo - 碼云 - 開源中國 (gitee.com)

35-tcpSocket-server · jbjnb/Qt demo - 碼云 - 開源中國 (gitee.com)

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

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

相關文章

linux 查看歷史命令列表來訪問之前的內容的命令是:history

在Linux中&#xff0c;要查看歷史命令列表以訪問之前的內容&#xff0c;你可以使用history命令。這個命令會顯示你當前shell會話&#xff08;或者&#xff0c;如果你指定了參數&#xff0c;可能是所有會話&#xff09;中執行過的命令列表。 基本用法 簡單地輸入history并按下…

設計模式使用場景實現示例及優缺點(結構型模式——代理模式、外觀模式)

結構型模式 代理模式&#xff08;Proxy Pattern&#xff09; 代理模式&#xff08;Proxy Pattern&#xff09;是一種結構型設計模式&#xff0c;它通過引入一個代理對象來控制對另一個對象的訪問。這個代理對象可以為被代理的對象提供額外的功能&#xff0c;例如訪問控制、延…

力扣844.比較含退格的字符串

力扣844.比較含退格的字符串 棧模擬 class Solution {public:bool backspaceCompare(string s, string t) {int n s.size(),m t.size();stack<char> s1,s2;for(int i0;i<n;i){s1.push(s[i]);if(s[i] #){if(s1.size() 1) s1.pop();else s1.pop(),s1.pop();}}for(i…

利用Python的sympy包求解一元多次方程

一元1次方程 import sympy as sp # 導入sympy包 x sp.Symbol(x) # 定義符號變量 f 2*x -8 # 定義要求解的一元1次方程 x sp.solve(f) # 調用solve函數求解方程 x[4]一元2次方程 import sympy as sp # 導入sympy包 x sp.Symbol(x) # 定義符號變量 f …

網絡安全合規建設

網絡安全合規建設 一、法律安全需求基本合規&#xff08;1&#xff09;《網絡安全法》重要節點等級保護政策核心變化 二、安全需求 業務剛需&#xff08;1&#xff09;內憂&#xff08;2&#xff09;外患 三、解決方法&#xff08;1&#xff09;總安全戰略目標圖&#xff08;2&…

廣匯汽車:救得起來嗎?

五折奔馳、六折寶馬...BBA們“腰斬式”大降價后正在引發連鎖反應。 國內第二大汽車經銷商——廣匯汽車&#xff0c;還好嗎&#xff1f; 受新能源品牌沖擊&#xff0c;近年來奔馳、寶馬等豪華燃油品牌銷量低迷&#xff0c;紛紛開啟降價模式&#xff0c;首當其沖的就是以廣匯汽車…

使用Python實現深度學習模型:跨平臺模型移植與部署

引言 隨著深度學習技術的快速發展,模型的跨平臺移植與部署變得越來越重要。無論是將模型從開發環境移植到生產環境,還是在不同的硬件平臺上運行,跨平臺部署都能顯著提高模型的實用性和可擴展性。本文將介紹如何使用Python實現深度學習模型的跨平臺移植與部署,并提供詳細的…

QT TCP多線程網絡通信

學習目標&#xff1a; TCP網絡通信編程 學習前置環境 運行環境:qt creator 4.12 QT TCP網絡通信編程-CSDN博客 Qt 線程 QThread類詳解-CSDN博客 學習內容 使用多線程技術實現服務端計數器 核心代碼 客戶端 客戶端&#xff1a;負責連接服務端&#xff0c;每次連接次數1。…

從零開始做題:MP3

題目 給出一個mp3文件 解題 右鍵->selection->save selection->另存為xxx.png即可 8750d5109208213f E:\逐鹿\MISC\tools\MP3Stego_1_1_19\MP3Stego>.\decode -X cipher.mp3 MP3StegoEncoder 1.1.19 See README file for copyright info Input file cipher.mp3…

未來代理IP的發展趨勢:創新、適應和可持續性

你是否好奇&#xff0c;未來代理IP將如何演變以適應日益復雜和全球化的網絡環境&#xff1f;讓我們探討一下代理IP技術在創新、適應性和可持續發展方面的未來前景。 1. 創新技術驅動 未來的代理IP將依托創新技術&#xff0c;如邊緣計算、區塊鏈和深度學習。邊緣計算技術的應用…

AcWing 5458:進水排水問題

【題目描述】 某已經蓄滿水的泳池內裝有 4 個水管。 前 2 個水管是進水管&#xff0c;單位時間的進水量分別為 a,b。 后 2 個水管是排水管&#xff0c;單位時間的排水量分別為 c,d。 請你計算&#xff0c;當 4 個水管同時工作時&#xff0c;是否可能將泳池里的水排干。【輸入格…

53-5 內網代理7 - CS上線不出網主機

靶場搭建: 這里就用之前內網代理的靶場,把web服務器這臺虛擬機關閉掉,用剩下的3臺加kali 各個虛擬機的網絡情況 kali - 可以連接外網win2008(之前的FTP服務器) 可以連接外網 win 7(之前的辦公電腦) 不出網主機 - 無法連接外網win2012 克隆機(之前的域控) - 無法連接…

視頻壓縮文件太大了怎么縮小?3個壓縮方法分享

視頻壓縮文件太大了怎么縮小&#xff1f;當視頻壓縮文件過大時&#xff0c;縮小其大小不僅能節省寶貴的存儲空間&#xff0c;還能顯著提升文件傳輸速度&#xff0c;特別是在網絡條件有限的情況下。通過專業的視頻壓縮軟件&#xff0c;可以有效減少文件體積&#xff0c;使視頻內…

python庫(9):prettytable庫快速實現ASCII表格

下面介紹一個快速制作ASCII表格庫——prettytable&#xff0c;可以方便地制作簡單表格。 1 安裝prettytable pip install -i https://pypi.tuna.tsinghua.edu.cn/simple prettytable 結果如下&#xff1a; 2 代碼實例 from prettytable import PrettyTable table PrettyTa…

【Python系列】深入解析 Python 中的 JSON 處理工具

&#x1f49d;&#x1f49d;&#x1f49d;歡迎來到我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦:kwan 的首頁,持續學…

兼容MySQL和PostgreSQL協議的數據庫

兼容MySQL和PostgreSQL協議的數據庫 一、Aurora二、TDSQL數據庫三、TDSQL-C數據庫四、TDSQL-C MySQL 版和 TDSQL MySQL 版的區別 一、Aurora Aurora是由亞馬遜網絡服務&#xff08;AWS&#xff09;提供的一種關系型數據庫引擎。它是在MySQL和PostgreSQL之上構建的&#xff0c;…

coco數據集格式計算mAP的python腳本

目錄 背景說明COCOeval 計算mAPtxt文件轉換為coco json 格式自定義數據集標注 背景說明 在完成YOLOv5模型移植&#xff0c;運行在板端后&#xff0c;通常需要衡量板端運行的mAP。 一般需要兩個步驟 步驟一&#xff1a;在板端批量運行得到目標檢測結果&#xff0c;可保存為yol…

【Django項目】基于Python+Django+MySQL的音樂網站系統項目

功能介紹 首頁&#xff1a;歌曲分類、歌曲搜索、熱門歌曲、熱門下載、新歌推薦 歌曲排行&#xff1a;歌曲分類、分頁功能 用戶板塊&#xff1a;用戶登陸/注冊、播放歷史 歌曲詳情&#xff1a;歌曲播放、當前播放列表、歌曲點評、歌曲播放插件、下載歌曲 系統后臺&#xff1a;歌…

MySQL體系架構解析

1.MySQL體系架構 1.1.MySQL的分支與變種 MySQL變種有好幾個,主要有三個久經考驗的主流變種:Percona Server,MariaDB和 Drizzle。它們都有活躍的用戶社區和一些商業支持,均由獨立的服務供應商支持。同時還有幾個優秀的開源關系數據庫,值得我們了解一下。 1.1.1.Drizzle …

【Sql Server修改列類型錯誤信息:對象名依賴于列】

Sql Server修改列類型錯誤信息&#xff1a;對象名依賴于列 報錯信息解決方法測試sql語句 報錯信息 修改表中列類型&#xff0c;發生報錯如下&#xff1a; [SQL Server]對象DF__Forecast___isCal__4E746892 依賴于 列isCalcFinished。 (5074) [42000] [Microsoft][ODBC Driver…