日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

QT示例:基于TCP 点对多Socket通讯(server,clients)

發(fā)布時(shí)間:2024/7/23 c/c++ 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 QT示例:基于TCP 点对多Socket通讯(server,clients) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

QT示例:基于TCP 點(diǎn)對(duì)多通訊(server,clients)

      • 一、服務(wù)器server
      • 二、客戶端Client

下載:基于TCP 點(diǎn)對(duì)多Socket通訊

一、服務(wù)器server

因?yàn)閷?duì)于客戶端來(lái)說(shuō),只能連接一個(gè)服務(wù)器。而對(duì)于服務(wù)器來(lái)說(shuō),它是面向多連接的,如何協(xié)調(diào)處理多客戶端連接就顯得尤為重要。

  • 注意問(wèn)題:
    每個(gè)新加入的客戶端,服務(wù)器給其分配一個(gè)SocketDescriptor后,就會(huì)emit newConnection()信號(hào),但分配好的SocketDecriptor并沒(méi)有通過(guò)newConnection()信號(hào)傳遞,所以用戶得不到這個(gè)客戶端標(biāo)識(shí)SocketDescriptor。同樣的,每當(dāng)服務(wù)器收到新的消息時(shí),客戶端會(huì)emit readReady()信號(hào),然而readReady()信號(hào)也沒(méi)有傳遞SocketDescriptor, 這樣的話,服務(wù)器端即使接收到消息,也不知道這個(gè)消息是從哪個(gè)客戶端發(fā)出的。
  • 解決的方法:
  • 通過(guò)重寫(xiě)==[virtual protected] void QTcpServer::incomingConnection(qintptr socketDescriptor)==,獲取soketDescriptor。自定義TcpClient類(lèi)繼承QTcpSocket,并將獲得的soketDescriptor作為類(lèi)成員。 這個(gè)方法的優(yōu)點(diǎn)是:可以獲取到soketDescriptor,靈活性高。缺點(diǎn)是:需要重寫(xiě)函數(shù)、自定義類(lèi)。
  • 在newConnection()信號(hào)對(duì)應(yīng)的槽函數(shù)中,通過(guò)QTcpSocket *QTcpServer::nextPendingConnection()函數(shù)獲取 新連接的客戶端:Returns the next pending connection as a connected QTcpSocket object. 雖然仍然得不到soketDescriptor,**但可以通過(guò)QTcpSocket類(lèi)的peerAddress()和peerPort()成員函數(shù)獲取客戶端的IP和端口號(hào),同樣是唯一標(biāo)識(shí)。 **優(yōu)點(diǎn):無(wú)需重寫(xiě)函數(shù)和自定義類(lèi),代碼簡(jiǎn)潔。缺點(diǎn):無(wú)法獲得SocketDecriptor,靈活性差。
  • 本文示例為第二種方法:
    1).pro 添加:

    QT += network

    2)主函數(shù) main.cpp 添加:

    #include "mytcpserver.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MyTcpServer w;w.show();return a.exec(); }

    3)MyTcpServer.h 添加:

    #include "mytcpserver.h" #include "ui_mytcpserver.h"MyTcpServer::MyTcpServer(QWidget *parent) :QMainWindow(parent),ui(new Ui::MyTcpServer) {ui->setupUi(this);// 一 、創(chuàng)建QTcpSever對(duì)象;tcpServer = new QTcpServer(this);ui->edtIP->setText(QNetworkInterface().allAddresses().at(1).toString()); //獲取本地IPui->btnConnect->setEnabled(true);ui->btnSend->setEnabled(false);// 設(shè)置默認(rèn)按鈕樣式ui->btnConnect->setStyleSheet("");connect(tcpServer, &QTcpServer::newConnection, this, &MyTcpServer::NewConnectionSlot); }MyTcpServer::~MyTcpServer() {delete ui; }// 二、監(jiān)聽(tīng)--斷開(kāi) void MyTcpServer::on_btnConnect_clicked() {if(ui->btnConnect->text()=="監(jiān)聽(tīng)"){bool ok = tcpServer->listen(QHostAddress::Any, ui->edtPort->text().toInt());if(ok){ui->btnConnect->setText("斷開(kāi)");ui->btnConnect->setStyleSheet("color: red;");ui->btnSend->setEnabled(true);}}else{for(int i=0; i<tcpClient.length(); i++) // 斷開(kāi)所有連接{tcpClient[i]->disconnectFromHost();bool ok = tcpClient[i]->waitForDisconnected(1000);if(!ok){// 處理異常QMessageBox::warning(this, tr("錯(cuò)誤"),tr("斷開(kāi)連接失敗!"), QMessageBox::Ok);}tcpClient.removeAt(i); // 從保存的客戶端列表中取去除}tcpServer->close(); // 不再監(jiān)聽(tīng)端口ui->btnConnect->setText("監(jiān)聽(tīng)");ui->btnConnect->setStyleSheet("");ui->btnSend->setEnabled(false);} }// 三、新連接建立的槽函數(shù) void MyTcpServer::NewConnectionSlot() {currentClient = tcpServer->nextPendingConnection();tcpClient.append(currentClient);ui->cbxConnection->addItem(tr("%1:%2").arg(currentClient->peerAddress().toString().split("::ffff:")[1]).arg(currentClient->peerPort()));connect(currentClient, &QTcpSocket::readyRead, this, &MyTcpServer::ReadData);connect(currentClient, &QTcpSocket::disconnected, this, &MyTcpServer::disconnectedSlot); }// 四、客戶端數(shù)據(jù)可讀信號(hào),對(duì)應(yīng)的讀數(shù)據(jù)槽函數(shù) void MyTcpServer::ReadData() {// 由于readyRead信號(hào)并未提供SocketDecriptor,所以需要遍歷所有客戶端for(int i=0; i<tcpClient.length(); i++){QByteArray buffer = tcpClient[i]->readAll();if(buffer.isEmpty()) // 客戶端 數(shù)據(jù)為空,則跳過(guò)continue;// 客戶端有數(shù)據(jù)則 獲取IP 和端口static QString IP_Port, IP_Port_Pre;IP_Port = tr("[%1:%2]:").arg(tcpClient[i]->peerAddress().toString().split("::ffff:")[1]).arg(tcpClient[i]->peerPort());// 若此次消息的地址與上次不同,則需顯示此次消息的客戶端地址if(IP_Port != IP_Port_Pre)ui->edtRecv->append(IP_Port);ui->edtRecv->append(buffer);//更新ip_portIP_Port_Pre = IP_Port;} }// 五、斷開(kāi)連接的槽函數(shù) void MyTcpServer::disconnectedSlot() {//由于disconnected信號(hào)并未提供SocketDescriptor,所以需要遍歷尋找for(int i=0; i<tcpClient.length(); i++){if(tcpClient[i]->state() == QAbstractSocket::UnconnectedState){// 刪除存儲(chǔ)在combox中的客戶端信息ui->cbxConnection->removeItem(ui->cbxConnection->findText(tr("%1:%2").arg(tcpClient[i]->peerAddress().toString().split("::ffff:")[1]).arg(tcpClient[i]->peerPort())));// 刪除存儲(chǔ)在tcpClient列表中的客戶端信息tcpClient[i]->destroyed();tcpClient.removeAt(i);}} }// 六、發(fā)送數(shù)據(jù) void MyTcpServer::on_btnSend_clicked() {QString data = ui->edtSend->toPlainText();if(data == "")return; // 文本輸入框?yàn)榭諘r(shí)//全部連接if(ui->cbxConnection->currentIndex() == 0){for(int i=0; i<tcpClient.length(); i++)tcpClient[i]->write(data.toLatin1()); //qt5除去了.toAscii()}//指定連接else{QString clientIP = ui->cbxConnection->currentText().split(":")[0]; // IP 地址int clientPort = ui->cbxConnection->currentText().split(":")[1].toInt(); // port 端口號(hào) // qDebug() << clientIP; // qDebug() << clientPort;for(int i=0; i<tcpClient.length(); i++){if(tcpClient[i]->peerAddress().toString().split("::ffff:")[1]==clientIP&& tcpClient[i]->peerPort()==clientPort){tcpClient[i]->write(data.toLatin1());return; //ip:port唯一,無(wú)需繼續(xù)檢索}}} }// 清楚窗口 void MyTcpServer::on_btnClear_clicked() {ui->edtRecv->clear(); }

    5)界面 mytcpserver.ui

    二、客戶端Client

    1).pro 添加:

    QT += network

    2)主函數(shù) main.cpp 添加:

    #include "mytcpclient.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MyTcpClient w;w.show();return a.exec(); }

    3)MyTcpClient.h 添加:

    #include <QMainWindow> #include <QTcpSocket> #include <QHostAddress> #include <QMessageBox>namespace Ui { class MyTcpClient; }class MyTcpClient : public QMainWindow {Q_OBJECTpublic:explicit MyTcpClient(QWidget *parent = 0);~MyTcpClient();private:Ui::MyTcpClient *ui;QTcpSocket *tcpClient;private slots://客戶端槽函數(shù)void ReadData();void ReadError(QAbstractSocket::SocketError);void on_btnConnect_clicked();void on_btnSend_clicked();void on_pushButton_clicked(); };

    4)MyTcpClient.cpp 添加:

    #include "mytcpclient.h" #include "ui_mytcpclient.h"MyTcpClient::MyTcpClient(QWidget *parent) :QMainWindow(parent),ui(new Ui::MyTcpClient) {ui->setupUi(this);// 一、初始化TCP客戶端tcpClient = new QTcpSocket(this); //實(shí)例化tcpClienttcpClient->abort(); //取消原有連接ui->btnConnect->setEnabled(true);ui->btnSend->setEnabled(false);connect(tcpClient, &QTcpSocket::readyRead, this, &MyTcpClient::ReadData);connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(ReadError(QAbstractSocket::SocketError))); }MyTcpClient::~MyTcpClient() {delete ui; }// 二、連接 void MyTcpClient::on_btnConnect_clicked() {if(ui->btnConnect->text()=="連接"){tcpClient->connectToHost(ui->edtIP->text(), ui->edtPort->text().toInt());if (tcpClient->waitForConnected(1000)) // 連接成功則進(jìn)入if{}{ui->btnConnect->setText("斷開(kāi)");ui->btnSend->setEnabled(true);}}else{tcpClient->disconnectFromHost();if (tcpClient->state() == QAbstractSocket::UnconnectedState || tcpClient->waitForDisconnected(1000)) //已斷開(kāi)連接則進(jìn)入if{}{ui->btnConnect->setText("連接");ui->btnSend->setEnabled(false);}} }// 三、讀取數(shù)據(jù) void MyTcpClient::ReadData() {QByteArray buffer = tcpClient->readAll();if(!buffer.isEmpty()){ui->edtRecv->append(buffer);} }// 四、發(fā)送數(shù)據(jù) void MyTcpClient::on_btnSend_clicked() {QString data = ui->edtSend->toPlainText();if(data != ""){tcpClient->write(data.toLatin1()); //qt5出去了.toAscii()} }// 連接錯(cuò)誤信息處理 void MyTcpClient::ReadError(QAbstractSocket::SocketError) {tcpClient->disconnectFromHost();ui->btnConnect->setText(tr("連接"));QMessageBox msgBox;msgBox.setText(tr("failed to connect server because %1").arg(tcpClient->errorString()));msgBox.exec(); }// 清空按鈕 void MyTcpClient::on_pushButton_clicked() {ui->edtRecv->clear(); }

    2)mytcpclient.ui 添加


    參考博客:
    QT 之TCP網(wǎng)絡(luò)編程

    總結(jié)

    以上是生活随笔為你收集整理的QT示例:基于TCP 点对多Socket通讯(server,clients)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 91.xxx.高清在线 | 久久精品免费在线 | 久久精品一二三区 | 中文字幕91视频 | 中文字幕精品一区二区精品 | 6080久久| 天天av网 | 桃色激情网| 国产正在播放 | 国产精品一区二区久久久 | 日批视频在线播放 | 欧美三级视频在线 | 爱爱亚洲 | 欧美中文字幕在线观看 | 91一区在线| 成人激情综合网 | 亚洲国产欧美视频 | 亚洲色图40p| 91入囗 | 在线观看三级视频 | 国产精视频 | 少妇激情一区二区三区视频 | 亚洲国产成人91porn | 亚洲精品久久视频 | 91免费精品视频 | 99国产揄拍国产精品 | 久久99久久久 | 一二三区在线视频 | 中文字幕免费高清在线观看 | 97视频在线观看免费 | 波多野结衣一区二区三区高清 | 国产欧美日韩精品区一区二污污污 | 亚洲一级在线观看 | 国产又粗又硬又长又爽的演员 | 午夜在线观看免费视频 | 欧美成人看片黄a免费看 | 人人艹人人爽 | 色丁香婷婷综合久久 | 伊人夜夜 | 久久精品黄aa片一区二区三区 | 欧美 日韩 中文字幕 | 久久精品视频偷拍 | sm捆绑调教视频 | 好大好舒服视频 | 青青草久久| 91高跟黑色丝袜呻吟在线观看 | 天堂а√在线最新版中文在线 | 天天干夜夜骑 | 日干夜操 | 亚洲视频网站在线观看 | 999福利视频 | 激情综合影院 | 久久日韩精品 | 午夜一区二区三区在线 | 好大好舒服视频 | 国产无遮挡免费视频 | 99热这里只有精品在线观看 | 福利在线一区二区 | 中文在线a在线 | 成人动作片 | bt天堂av| 久久综合日本 | 国产福利免费观看 | 久草观看视频 | 欧美色拍| 成年人免费在线观看视频网站 | 免费黄色欧美 | 国产探花在线观看 | 羞羞涩| 激情内射亚洲一区二区三区爱妻 | 成人欧美一级特黄 | 久久久久人| www.狠狠撸.com| 一级大片视频 | 你懂的在线观看视频 | 亚洲国产欧美日韩在线 | 91精品国产乱码久久 | 日本视频免费看 | 国产高清不卡一区 | 免费在线看污视频 | 成人宗合 | 亚洲综合首页 | 人妻精品久久久久中文字幕69 | 大学生高潮无套内谢视频 | 亚洲啪av永久无码精品放毛片 | 97桃色| 亚洲天堂av一区二区 | 国产日本欧美在线 | 97精品人妻一区二区三区在线 | 免费精品视频在线观看 | 中国av一区二区三区 | 国产女同91疯狂高潮互磨 | 亚洲热热 | 久久93 | 艹久久 | 国产国语videosex另类 | 99精品黄色 | 真性中出 | 日本黄在线观看 |