您好,登錄后才能下訂單哦!
這篇文章主要介紹“Qt中網絡編程怎么實現”,在日常操作中,相信很多人在Qt中網絡編程怎么實現問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Qt中網絡編程怎么實現”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
TCP/IP實際上是一個協同工作的通信家族,為網絡通信提供通路。為方便討論TCP/IP協議族,大體上分為三部分:
①、Internet協議(IP)。
②、傳輸控制協議(TCP)和用戶數據報協議(UDP)。
③、處于TCP和UDP之上的一組應用協議。它們包括:Telnet,文件傳送協議(FTP),域名服務協議(DNS)和簡單的郵件傳送程序(SMTP)等。
udp協議(用戶數據報協議),它與TCP協議完全相反。提供不可靠、無連接和基于數據報的服務。不可靠意味著UDP協議無法保證數據從發送端正確的發送到接收端。如果數據在中途丟失,或者目的端通過數據校驗發現數據錯誤而將其丟棄,則UDP協議的應用程序通常要自己處理數據確認、超時重傳等邏輯性。
1.3.1、tcp/ip
tcp只需要知道它是一種通訊方式就可以了,還有一個udp,那這兩者之間的關系是什么。TCP/IP協議是一個協議簇。里面包括很多協議的。UDP只是其中的一個。之所以命名為TCP/IP協議,因為TCP,IP協議是兩個很重要的協議,就用他兩命名了,tcp是打電話,udp是發短信。
Ip(網絡之間互連的協議,外文是Internet Protocol的外語縮寫,中文縮寫為“網協”。縮寫為IP),通過設置ip地址就可以去訪問網絡,用的最多的ip協議是ipv4(ip協議v版本4),還有一個版本為ipv6,ipv4不夠用了,Ipv4版本是32位的,一般分成4段,內存中就是一個無符號32位的整數,ipv6的話就是一個64位的整數,通過位數就知道ipv4和ipv6的區別,能保存多少個的地址。只不過用戶并不需要去搞清楚。
現在常用的ip是127.0.0.1這個樣子,點分格式(一個字符串)。點所隔開的區間就是一個字符。Ip地址有ABC三類地址。前三段是用來確定路由器,確定主機連上外圍網上的哪一個路由,最后一段用來確定主機,確定主機是這個路由器上的第多少臺,最多255臺,0一般是用來做網關的。
ip對應的還有一個子網掩碼
子網掩碼(subnet mask)又叫網絡掩碼、地址掩碼、子網絡遮罩,它是一種用來指明一個IP地址的哪些位標識的是主機所在的子網,以及哪些位標識的是主機的位掩碼。子網掩碼不能單獨存在,它必須結合IP地址一起使用。子網掩碼只有一個作用,就是將某個IP地址劃分成網絡地址和主機地址兩部分。子網掩碼--屏蔽一個IP地址的網絡部分的"全1"比特模式。
對于A類地址來說,默認的子網掩碼是255.0.0.0;
對于B類地址來說默認的子網掩碼是255.255.0.0;
對于C類地址來說默認的子網掩碼是255.255.255.0。
子網掩碼,一般是255.255.255.0。
ip地址的前三段來確定路由器,最后一段是主機位置。所以子網掩碼理解為子網遮罩編碼。
1.3.2、Socket
pc機對應在網絡上就是一臺主機,在這臺Pc機上面會有多個進程需要訪問網絡,所以需要在Pc機的操作系統上面去有處理網絡的東西,前人就定了一個“套接字”來專門處理網絡(源IP地址和目的IP地址以及源端口號和目的端口號的組合稱為套接字)。把一個主機拆分為N個網絡端口(Port)一共會有65536個,short的最大范圍,在這些端口當中,要注意0-5000的端口一般不用,用來給操作系統的進程來使用的。一般會用靠后一點的端口,這樣比較安全,當然還有一些端口,比如8080端口也會用的比較多,一個進程只能占用一個端口,不能多進程占用同一個端口的情況,一個進程可以占用多個端口的,或者嚴謹一點,同一時刻一個端口只能由一個進程使用。網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個socket。
建立網絡通信連接至少要一對端口號(socket)。socket本質是編程接口(API),對TCP/IP的封裝,TCP/IP也要提供可供程序員做網絡開發所用的接口,這就是Socket編程接口。通常也稱作"套接字",用于描述IP地址和端口,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。
1.3.3、tcp通信模型
c/s模型,客戶端(c)/服務器(s)模型,一個服務器來對應多個客戶端的處理,一對多的關系。以下步驟沒有特殊指明,服務器和客戶端是都需要有的步驟:
1.準備工作,根據自己使用語言所有庫函數導入;
2. 確定版本信息,要確定socket版本,ip是有v4和v6兩個版本的;
3. 創建socket,使用socket函數
4. 初始化協議地址簇 ;
5. 綁定,使用bind函數,把協議地址簇和socket綁定在一起,客戶端不要綁定;
6. 服務器端有,需要監聽 listen函數,客戶端不需要這一步;
7. 服務器端需要接受連接,客戶端需要連接服務器;
8. 連接完成之后,開始通訊,收發數據;
9. 通訊完成后關閉socket;
開始前在項目的.pro文件中加入這個network
tcpsever.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QNetworkInterface>//網絡信息 #include <QHostAddress>//id地址 #include <QTcpServer> //tcp協議 #include <QTcpSocket> //socket套接字 #include <QDebug> #include <QMessageBox> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_pushButton_listen_clicked(); void on_pushButton_send_clicked(); void newconnectslot();//連接 void readyRead_Slot();//讀取信息 void disconnected_Slot();//斷開 private slots: QString list_all_IPV4(); private: Ui::Widget *ui; //2、設置服務端和接收客戶端的對象 QTcpServer *tcpServer; QTcpSocket *tcpSocket; }; #endif // WIDGET_H
tcpsever.cpp
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); //3、創建服務器對象 tcpSocket=NULL; tcpServer=new QTcpServer(this); //5、有客戶端連接服務器發送信號 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newconnectslot())); QMessageBox::information(this,"本機聯網端口顯示",this->list_all_IPV4()); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_listen_clicked() { //4、開始監聽 QString sever_Address = ui->lineEdit_address->text(); quint16 port = ui->lineEdit_port->text().toInt(); QHostAddress host = QHostAddress(sever_Address); if(!tcpServer->isListening()){ //監聽綁定的ip地址 if(!tcpServer->listen(host,port)) { qDebug()<<tcpServer->errorString(); return; }else{ qDebug()<<"監聽成功"; ui->pushButton_listen->setText("停止監聽"); } }else{ tcpServer->close(); ui->pushButton_listen->setText("開始監聽"); } } QString Widget::list_all_IPV4(){ QString str; QList<QHostAddress> list=QNetworkInterface::allAddresses(); //獲取本機的所有網卡的ip地址 foreach (QHostAddress address, list) { if(address.isNull()) continue; QAbstractSocket::NetworkLayerProtocol portocol=address.protocol(); //只提取IPv4地址 if(portocol!=QAbstractSocket::IPv4Protocol) continue; str = str +'\n\t'+address.toString() + '\n\t\t'; } return str; }; void Widget::newconnectslot(){ //6、接受客戶端 tcpSocket = tcpServer->nextPendingConnection(); QString client_Info = "客戶端:" + tcpSocket->peerAddress().toString() +" "+ "端口號:" + QString::number(tcpSocket->peerPort()); ui->textBrowser_clientInfo->setText(client_Info); //發送信號和讀取關聯 connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); //斷開信號關聯客戶端 connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(disconnected_Slot())); }; void Widget::on_pushButton_send_clicked() { if(tcpSocket != nullptr) { if(tcpSocket->isWritable()) { QString send = ui->plainTextEdit_sendInfo->toPlainText(); QByteArray sendarr = send.toLocal8Bit();//本地字符集與Unicode的轉換 tcpSocket->write(sendarr); } } } void Widget::readyRead_Slot(){ if(tcpSocket != nullptr) { if(tcpSocket->isReadable()) { QByteArray recvAll = tcpSocket->readAll();//將數據全部讀取 QString str = str.fromLocal8Bit(recvAll.data()); ui->textBrowser_recv->append(str); } } }; void Widget::disconnected_Slot(){ QMessageBox::information(this,"Client Close Signal","有客戶離開"); };
tcpclient,h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QNetworkInterface>//網絡信息 #include <QHostAddress>//id地址 #include <QTcpServer> //tcp協議 #include <QTcpSocket> //socket套接字 #include <QDebug> #include <QMessageBox> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_pushButton_listen_clicked(); void on_pushButton_send_clicked(); void readyRead_Slot();//讀取信息 void disconnected_Slot();//斷開 private: Ui::Widget *ui; QTcpSocket *client; bool socket_state; }; #endif // WIDGET_H
tcpclient.cpp
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); client = new QTcpSocket(this); socket_state = false; connect(client, SIGNAL(disconnected()), this, SLOT(disconnected_Slot())); connect(client, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_listen_clicked() { QString ipAddress = ui->lineEdit_address->text(); qint16 port = ui->lineEdit_port->text().toInt(); if(!socket_state) { client->connectToHost(ipAddress,port); if(client->waitForConnected(3000)){//等待3s,連不上會返回假 ui->pushButton_listen->setText("斷開連接"); socket_state = true; }else{ qDebug()<<client->errorString(); return; } }else{ client->close(); QMessageBox::information(this,"消息提示","已經離開!",QMessageBox::Yes); ui->pushButton_listen->setText("連接"); socket_state = false; } } void Widget::readyRead_Slot(){ QByteArray data=client->readAll(); QString str=str.fromLocal8Bit(data.data()); ui->textBrowser_recv->append(str); }; void Widget::disconnected_Slot(){ qDebug()<<"離開"; } void Widget::on_pushButton_send_clicked() { QString datastr = ui->plainTextEdit_sendInfo->toPlainText(); QByteArray da = datastr.toLocal8Bit(); if(client->isOpen() && client->isValid()){ client->write(da); } }
初始操作同TCP操作
udp_test.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> //1、包含相關的頭文件 #include <QHostAddress> #include <QUdpSocket> #include <QDebug> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_pushButtonSend_clicked(); void readyReadSlot(); void on_pushButtonCLose_clicked(); private: Ui::Widget *ui; //2、定義udp對象 QUdpSocket *udpSocket; }; #endif // WIDGET_H
udp_test.cpp
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); //3、創建對象 udpSocket=new QUdpSocket(this); //4、關聯讀取的信號與槽 connect(udpSocket,SIGNAL(readyRead()),this,SLOT(readyReadSlot())); } Widget::~Widget() { delete ui; } void Widget::on_pushButtonSend_clicked() { udpSocket->writeDatagram(ui->plainTextEdit_sendInfo->toPlainText().toLocal8Bit(),//內容 QHostAddress(ui->lineEditIp->text()),//發送ip ui->lineEditPort->text().toInt());//發送的地址 } void Widget::on_pushButtonCLose_clicked() { udpSocket->bind(ui->lineEditPort_2->text().toInt()); } void Widget::readyReadSlot(){ quint64 size = udpSocket->bytesAvailable();//讀取發過來的消息大小 QByteArray ba; ba.resize(size); QHostAddress address; quint16 port; udpSocket->readDatagram(ba.data(),size,&address,&port); QString str = QString::fromLocal8Bit(ba.data()); ui->textEdit_recvInfo->append(str); }
到此,關于“Qt中網絡編程怎么實現”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。