国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Qt 服務器/客戶端TCP通訊

這篇具有很好參考價值的文章主要介紹了Qt 服務器/客戶端TCP通訊。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。


最近需要用到TCP/IP通訊,這邊就先找個簡單的例程學習一下。Qt的TCP通訊編程可以使用QtNetwork模塊,QtNetwork模塊提供的類能夠創(chuàng)建基于TCP/IP的客戶端與服務端應用程序,一般會使用QTcpSocket、QTcpServer類

TCP和UDP通訊

網(wǎng)絡通信方式主要有兩種:TCP與UDP。以下拷貝網(wǎng)絡上總結(jié)兩者之間的區(qū)別:
1、TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發(fā)送數(shù)據(jù)之前不需要建立連接
2、TCP提供可靠的服務。也就是說,通過TCP連接傳送的數(shù)據(jù),無差錯,不丟失,不重復,且按序到達;UDP盡最大努力交付,即不保證可靠交付
3、TCP面向字節(jié)流,實際上是TCP把數(shù)據(jù)看成一連串無結(jié)構(gòu)的字節(jié)流;UDP是面向報文的。
UDP沒有擁塞控制,因此網(wǎng)絡出現(xiàn)擁塞不會使源主機的發(fā)送速率降低(對實時應用很有用,如IP電話,實時視頻會議等)
4、每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信
5、TCP首部開銷20字節(jié);UDP的首部開銷小,只有8個字節(jié)
6、TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道。

另外在編程時TCP通訊可能涉及到粘包/拆包。UDP是基于報文傳輸?shù)模l(fā)送幾次Write(),接收端就會用幾次Read(),每次讀取一個報文,報文間不合并,多于緩沖區(qū)的報文會丟棄。TCP是基于數(shù)據(jù)流傳輸?shù)模琖rite()和Read()的次數(shù)不固定,報文間會以隨機的方式合并,這就需要在接收時進行粘包/拆包處理,這里暫不涉及。

服務器

TCP服務器流程一般包括:
1.創(chuàng)建QTcpServer對象
2.啟動服務器(監(jiān)聽)調(diào)用成員方法listen
3.當有客戶端鏈接時候會發(fā)送newConnection信號,觸發(fā)槽函數(shù)接受連接
4.QTcpsocket發(fā)送數(shù)據(jù)用成員方法write
5.當客戶端有數(shù)據(jù)進來,QTcpSocket對象就會發(fā)送readyRead信號,關(guān)聯(lián)槽函數(shù)讀取數(shù)據(jù),使用read或readall方法

找了一個博文,見引用,寫得很詳細,這邊幾乎也是全搬過來。

源碼

源碼如下

#include "widget.h"
#include "ui_widget.h"
#include <QtNetwork>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    /*讀取本機網(wǎng)卡信息...*/
    QString localHostName = QHostInfo::localHostName();
    QHostInfo info = QHostInfo::fromName(localHostName);

    /*將本機所有的IPV4地址添加到comBox_hostIP下.*/
    foreach(QHostAddress ipAddress, info.addresses())
    {
        if(ipAddress.protocol() == QAbstractSocket::IPv4Protocol)
        {
            qDebug() << ipAddress.toString();
            ui->comBox_hostIP->addItem(ipAddress.toString());
        }
    }
    ui->comBox_hostIP->addItem("127.0.0.1");
    ui->comBox_hostIP->setCurrentIndex(ui->comBox_hostIP->count()-1);
    ui->lineEdit_Port->setText("12345");

    server = new QTcpServer(this);
    connect(server, &QTcpServer::newConnection, this,&Widget::on_newConnection);

}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushBtn_listen_clicked()
{
    /*監(jiān)聽本地IP加端口號.*/
      if(server->listen(QHostAddress(ui->comBox_hostIP->currentText()), ui->lineEdit_Port->text().toInt()) == false)
      {
          /*監(jiān)聽失敗,打印信息.*/
          qDebug()<<"listen false";
      }
      else
      {
          /*監(jiān)聽成功,則將一些控件鎖死.*/
          ui->pushBtn_listen->setDisabled(true);
          ui->lineEdit_Port->setDisabled(true);
          ui->comBox_hostIP->setDisabled(true);
          qDebug()<<"listen successfully";
          /*激活關(guān)閉按鈕*/
          ui->pushBtn_close->setEnabled(true);
      }

}

void Widget::on_newConnection()
{
    /*獲取新連接客戶端的socket*/
    QTcpSocket *socket = server->nextPendingConnection();

    /*將這個socket添加到List容器中...*/
    sockList.append(socket);

    /*獲取客戶端的IP地址和端口號信息,并轉(zhuǎn)換為字符串.*/
    QString info = socket->peerAddress().toString() \
                   + ':' + QString::number(socket->peerPort());

    /*將信息打印到文本框.*/
    ui->textEdit_rcv->append("Connected:"+info);

    /*將客戶端的信息添加到comBox_clientIP下.*/
    ui->comBox_clientIP->addItem(info);

    /*將新連接的socket對象的可以讀取信號連接到接收槽函數(shù).*/
    connect(socket, &QTcpSocket::readyRead, this, &Widget::on_recv);
    /*將新連接的socket對象的斷開連接信號連接到斷開槽函數(shù).*/
    connect(socket, &QTcpSocket::disconnected, this, &Widget::on_disconnect);

    if(ui->comBox_clientIP->count()==2)
        ui->comBox_clientIP->insertItem(0,"All");

}

void Widget::on_recv()
{
    /*找到觸發(fā)信號的那個socket對象.*/
    QTcpSocket *sock = qobject_cast<QTcpSocket *>(sender());

    /*讀取信息并轉(zhuǎn)化為字符串.*/
    QString info = "From " + sock->peerAddress().toString() \
            + ':' + QString::number(sock->peerPort());
    /*將客戶端的信息打印到文本框.*/
    ui->textEdit_rcv->append(info);
    /*將接收到的數(shù)據(jù)也打印到文本框.*/
    ui->textEdit_rcv->append(sock->readAll());


}

void Widget::on_disconnect()
{
    /*找到觸發(fā)信號的那個socket對象.*/
    QTcpSocket *sock = qobject_cast<QTcpSocket *>(sender());
    sockList.removeOne(sock);

    /*讀取信息并轉(zhuǎn)化為字符串.*/
    QString clientinfo = sock->peerAddress().toString() \
            + ':' + QString::number(sock->peerPort());

    /*將客戶端的信息打印到文本框.*/
    ui->textEdit_rcv->append(clientinfo+"   Disconneted!");

     /*根據(jù)字符串找到comBox_clientIP中的對應元素的索引號*/
     int index = ui->comBox_clientIP->findText(clientinfo);
     /*刪除那個元素.*/
     ui->comBox_clientIP->removeItem(index);

    /*將接收到的數(shù)據(jù)也打印到文本框.*/
//    ui->textEdit_rcv->append(sock->readAll());
     if(ui->comBox_clientIP->count()<=2)
         ui->comBox_clientIP->removeItem(0);

    /*將新連接的socket對象的可以讀取信號與接收槽函數(shù)斷開.*/
    disconnect(sock, &QTcpSocket::readyRead, this, &Widget::on_recv);
    /*將新連接的socket對象的斷開連接信號與斷開槽函數(shù)斷開.*/
    disconnect(sock, &QTcpSocket::disconnected, this, &Widget::on_disconnect);
}


void Widget::on_pushBtn_clear_clicked()
{
    ui->textEdit_rcv->clear();
}



void Widget::on_pushBtn_send_clicked()
{
    if(currSock == NULL)
    {
        foreach(QTcpSocket *sock, sockList)
        {
            sock->write(ui->textEdit_tx->toPlainText().toUtf8());
        }
    }
    else
    {
        /*如果選擇的是一個特定的客戶端,則只向它發(fā)送.*/
        currSock->write(ui->textEdit_tx->toPlainText().toUtf8());
    }

}


void Widget::on_comBox_clientIP_currentTextChanged(const QString &arg1)
{
    if(arg1 == "All")
      {
          currSock = NULL;
          return;
      }

      if (sockList.empty())
          return;

      /*不然就讀取選中的信息,將其拆分為IP地址和端口號.*/
      QStringList info = arg1.split(':');
      QString ip = info[0];
      int port = info[1].toInt();

      /*遍歷容器,找到對應的那個socket.*/
      foreach(QTcpSocket *sock, sockList)
      {
          if(sock->peerAddress().toString() == ip && sock->peerPort() == port)
          {
              /*當前sock指針指向找到的那個socket.*/
              currSock = sock;
              break;
          }
      }

}


void Widget::on_pushBtn_kickoff_clicked()
{
    if(currSock == NULL)
    {
        foreach(QTcpSocket *sock, sockList)
        {
            sock->close();
        }
    }
    else
    {
        currSock->close();

    }

}


void Widget::on_pushBtn_close_clicked()
{
    currSock = NULL;
    /*關(guān)閉監(jiān)聽.*/
    server->close();
    /*將一些控件恢復.*/
    ui->pushBtn_close->setDisabled(true);
    ui->pushBtn_listen->setEnabled(true);
    ui->lineEdit_Port->setEnabled(true);
    ui->comBox_hostIP->setEnabled(true);
    /*遍歷之前全部連接的socket,并一一斷開.*/
    foreach(QTcpSocket *sock, sockList)
    {
        sock->close();
    }

}

客戶端

客戶端更簡單些,基本流程如下:
1.創(chuàng)建QTcpSocket對象
2.鏈接服務器connectToHost
3.QTcpsocket發(fā)送數(shù)據(jù)用成員方法write
4.當對方有數(shù)據(jù)來,QTcpSocket對象就會發(fā)送readyRead信號,關(guān)聯(lián)槽函數(shù)讀取數(shù)據(jù)

參考了另一篇博文,代碼也是幾乎照抄。

源碼

#include "tcpclient.h"
#include "ui_tcpclient.h"

TcpClient::TcpClient(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::TcpClient)
{
    ui->setupUi(this);
    m_socket = new QTcpSocket();
    ui->lEdit_serverIP->setText("127.0.0.1");
    ui->lEdit_serverPort->setText("12345");
    ui->Btn_connect->setEnabled(true);
    ui->Btn_Send->setEnabled(false);
}

TcpClient::~TcpClient()
{
    delete this->m_socket;
    delete ui;
}



void TcpClient::on_Btn_connect_clicked()
{
    if(ui->Btn_connect->text() == tr("Connect"))
    {
        QString IP;
        int port;

        //獲取IP地址
        IP = ui->lEdit_serverIP->text();
        //獲取端口號
        port = ui->lEdit_serverPort->text().toInt();

        //取消已有的連接
        m_socket->abort();
        //連接服務器
        m_socket->connectToHost(IP, port);

        //等待連接成功
        if(!m_socket->waitForConnected(30000))
        {
            qDebug() << "Connection failed!";
            ui->textEdit_recv->append("Connection failed!");
            return;
        }
        qDebug() << "Connect successfully!";

        //發(fā)送按鍵使能
        ui->Btn_Send->setEnabled(true);
        //修改按鍵文字
        ui->Btn_connect->setText("Disconnect");
        ui->textEdit_recv->append("Connect successfully!");
        connect(m_socket,&QTcpSocket::readyRead, this,&TcpClient::socket_readData);
        connect(m_socket,&QTcpSocket::disconnected, this,&TcpClient::socket_disconnect);

    }
    else
    {
        //斷開連接
        m_socket->disconnectFromHost();
        //修改按鍵文字
        ui->Btn_connect->setText("Connect");
        ui->Btn_Send->setEnabled(false);

        disconnect(m_socket,&QTcpSocket::readyRead, this,&TcpClient::socket_readData);
        disconnect(m_socket,&QTcpSocket::disconnected, this,&TcpClient::socket_disconnect);
    }

}




void TcpClient::on_Btn_Send_clicked()
{
    qDebug() << "Send: " << ui->textEdit_tx->toPlainText();
     //獲取文本框內(nèi)容并以ASCII碼形式發(fā)送
    m_socket->write(ui->textEdit_tx->toPlainText().toLatin1());
    m_socket->flush();

}

void TcpClient::socket_readData()
{
    QByteArray buffer;
    //讀取緩沖區(qū)數(shù)據(jù)
    buffer = m_socket->readAll();
    if(!buffer.isEmpty())
    {
//        QString str = ui->textEdit_recv->toPlainText();
//        str+=tr(buffer)+"\n";
        //刷新顯示
         ui->textEdit_recv->append("From server: " +tr(buffer) );
//        ui->textEdit_recv->setText(str);
    }

}

void TcpClient::socket_disconnect(){

    //發(fā)送按鍵失能
    ui->Btn_Send->setEnabled(false);
    //修改按鍵文字
    ui->Btn_connect->setText("Connect");
    qDebug() << "Disconnected...";
    ui->textEdit_recv->append("Disconnected!");
    disconnect(m_socket,&QTcpSocket::readyRead, this,&TcpClient::socket_readData);
    disconnect(m_socket,&QTcpSocket::disconnected, this,&TcpClient::socket_disconnect);
}


void TcpClient::on_Btn_clear_clicked()
{
    ui->textEdit_recv->clear();
}

結(jié)果

Qt 服務器/客戶端TCP通訊基本功能都有,程序運行正確無誤哈??

引用

Qt學習記錄之簡單的TCP服務器
Qt 實現(xiàn)簡單的TCP通信
QT之TCP通信
TCP粘包產(chǎn)生的原因、解決方法及Qt項目代碼實現(xiàn)文章來源地址http://www.zghlxwxcb.cn/news/detail-426186.html

到了這里,關(guān)于Qt 服務器/客戶端TCP通訊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • Qt多線程TCP服務器客戶端傳輸文件

    Qt多線程TCP服務器客戶端傳輸文件

    TCP是面向連接的運輸層協(xié)議。應用程序在使用TCP協(xié)議之前,必須先建立TCP連接。在傳送數(shù)據(jù)完畢后,必須釋放已經(jīng)建立的TCP連接。 每一條TCP連接只能有兩個端點,每一條TCP連接只能是點對點的(一對一)。 TCP提供可靠交付的服務。通過TCP 連接傳送的數(shù)據(jù),無差錯、不丟失、不

    2024年02月13日
    瀏覽(17)
  • QT下的多線程TCP客戶端和服務器

    qt下的QTcpSocket在同一個線程使用時沒有問題的,但是如果進行跨線程,很容易出現(xiàn)問題。那么有什么方法可以跨線程進行使用嗎? 答案是肯定的:使用QThread的movetothread可以完成擴線程接收。 首先是基于QTcpSocket的類 頭文件tcpsocket.h 然后是cpp文件tcpsocket.cpp 再次基礎上,創(chuàng)建

    2024年01月17日
    瀏覽(24)
  • UDP通訊(服務器/客戶端)

    UDP通訊(服務器/客戶端)

    前言:UDP通訊實現(xiàn)比較簡單,單某些情況下也會使用,建議先看一下說明,然后運行代碼感受一下。 ????????傳輸層主要應用的協(xié)議模型有兩種,一種是TCP協(xié)議,另外一種則是UDP協(xié)議。TCP協(xié)議在網(wǎng)絡通信中占主導地位,絕大多數(shù)的網(wǎng)絡通信借助TCP協(xié)議完成數(shù)據(jù)傳輸。但U

    2024年02月03日
    瀏覽(31)
  • 【網(wǎng)絡】UDP通訊(服務器/客戶端)

    【網(wǎng)絡】UDP通訊(服務器/客戶端)

    前言:UDP通訊實現(xiàn)比較簡單,單某些情況下也會使用,建議先看一下說明,然后運行代碼感受一下。 ????????傳輸層主要應用的協(xié)議模型有兩種,一種是TCP協(xié)議,另外一種則是UDP協(xié)議。TCP協(xié)議在網(wǎng)絡通信中占主導地位,絕大多數(shù)的網(wǎng)絡通信借助TCP協(xié)議完成數(shù)據(jù)傳輸。但U

    2024年02月12日
    瀏覽(21)
  • TCP實現(xiàn)服務器和客戶端通信

    TCP實現(xiàn)服務器和客戶端通信

    目錄 TCP介紹 代碼實現(xiàn) server(服務器端) 代碼分析 client(客戶端) 代碼分析 結(jié)果展示 TCP (Transmission Control Protocol) 是一種面向連接的協(xié)議,用于在計算機網(wǎng)絡中傳輸數(shù)據(jù)。TCP 可以確保數(shù)據(jù)的可靠傳輸,即使在網(wǎng)絡環(huán)境不穩(wěn)定的情況下也能夠保證數(shù)據(jù)的完整性和順序。以下是

    2024年02月15日
    瀏覽(39)
  • 簡易TCP客戶端和服務器端通信

    #includeiostream #include winsock2.h ? #include ws2tcpip.h ? #includestdlib.h using namespace std; #define ?BUF_SIZE ?1024 int main() { ? ? cout \\\"客戶端\\\" endl; ? ? //設置Winsock版本, ? ? WSADATA ? wsaData; ? ? if (WSAStartup(MAKEWORD(2, 2), wsaData) != 0) ? ? { ? ? ? ? cout \\\"error\\\" endl; ? ? ? ? exit(1); ? ? } ? ? //創(chuàng)建通

    2024年04月29日
    瀏覽(23)
  • 【Micropython基礎】TCP客戶端與服務器

    【Micropython基礎】TCP客戶端與服務器

    MicroPython 是 Python 的一種精簡實現(xiàn),旨在運行于微控制器和嵌入式系統(tǒng)等資源受限的環(huán)境中。它提供了一種簡單而強大的方式來編寫和運行 Python 代碼,使開發(fā)人員能夠快速地創(chuàng)建各種嵌入式應用程序。 在嵌入式系統(tǒng)中,網(wǎng)絡通信是一個常見的需求,而 TCP(傳輸控制協(xié)議)是

    2024年04月28日
    瀏覽(30)
  • TCP客戶端及服務器端開發(fā)實踐

    TCP客戶端及服務器端開發(fā)實踐

    ① TCP客戶端應用程序開發(fā) ② TCP服務器端應用程序開發(fā) 客戶端程序是指運行在用戶設備上的程序,服務端程序是指運行在服務器設備上的程序,專門為客戶端提供數(shù)據(jù)服務。那如何記憶呢? 主動發(fā)起建立連接請求的是客戶端程序,等待接受連接請求的是服務端程序。 開發(fā)流

    2024年04月09日
    瀏覽(27)
  • TCP服務器監(jiān)測客戶端異常退出方法

    ????????作為服務器必須得具備監(jiān)測客戶端狀態(tài)得機制,以保證客戶端處于不同的狀態(tài),服務器進行不同得狀態(tài)處理,依次來提高實時性,可控性,并且有利于服務器得內(nèi)存管理。其中客戶端得異常處理就屬于其中得一種。 ????????客戶端得斷開情形無非就兩種情況:

    2024年02月09日
    瀏覽(33)
  • 用C語言搭建TCP服務器/客戶端

    用C語言搭建TCP服務器/客戶端

    1.TCP流程圖 2.TCP編程 服務器 客戶端 ????????以上就是用c語言搭建的tcp服務器和客戶端,IP地址的地方可以根據(jù)自己本機的IP地址去修改(在命令提示符中可以使用ifconfig命令查看本機IP地址),端口號用的是6666,也可自己修改,但是IP地址和端口號服務器和客戶端必須一至。

    2024年02月09日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包