參考文章:qt socket通信
Socket通信
Qt中提供的所有的Socket類都是非阻塞的。
Qt中常用的用於socket通信的套接字類:
- QTcpServer
用於TCP/IP通信, 作為服務器端套接字使用
- QTcpSocket
用於TCP/IP通信,作為客戶端套接字使用。
- QUdpSocket
用於UDP通信,服務器,客戶端均使用此套接字。
TCP/IP
在Qt中實現TCP/IP服務器端通信的流程:
- 創建套接字
- 將套接字設置為監聽模式
-
等待並接受客戶端請求
可以通過QTcpServer提供的void newConnection()信號來檢測是否有連接請求,如果有可以在對應的槽函數中調用nextPendingConnection函數獲取到客戶端的Socket信息(返回值為QTcpSocket*類型指針),通過此套接字與客戶端之間進行通信。
-
接收或者向客戶端發送數據
接收數據:使用read()或者readAll()函數
發送數據:使用write()函數
客戶端通信流程:
-
創建套接字
-
連接服務器
可以使用QTcpSocket類的connectToHost()函數來連接服務器。
-
向服務器發送或者接受數據
關於“套接字”
server端:
#ifndef SERVERWIDGET_H #define SERVERWIDGET_H #include <QWidget> #include <QTcpServer> //監聽套接字 #include <QTcpSocket> //通信套接字 namespace Ui { class serverWidget; } class serverWidget : public QWidget { Q_OBJECT public: explicit serverWidget(QWidget *parent = 0); ~serverWidget(); private slots: void on_buttonSend_clicked(); void on_buttonClose_clicked(); private: Ui::serverWidget *ui; QTcpServer *tcpServer; //監聽套接字 QTcpSocket *tcpSocket; //通信套接字 }; #endif // SERVERWIDGET_H
#include "serverwidget.h" #include "ui_serverwidget.h" #pragma execution_character_set("utf-8") serverWidget::serverWidget(QWidget *parent) : QWidget(parent), ui(new Ui::serverWidget) { ui->setupUi(this); tcpServer = NULL; tcpSocket = NULL; //監聽套接字,指定父對象,讓其自動回收空間 tcpServer = new QTcpServer(this); //1.QTcpServer對象負責監聽是否有客戶端連接此服務器。它是通過這樣一個函數監聽的 //第一個參數表示服務器監聽的地址,如果后面是Any表示監聽本機的所有網口的,第二個參數表示監聽的網絡端口 tcpServer->listen(QHostAddress::Any, 8888); setWindowTitle("Sever"); //2.如果服務器監聽到有客戶端和它進行連接,服務器就會觸發newConnection這個信號。同時客戶端一旦和服務器連接成功, //客戶端會觸發connected這個信號,表示已經成功和服務器連接。 connect(tcpServer, &QTcpServer::newConnection, [=]() { //3.當服務器和客戶端建立好連接之后,服務器需要返回一個QTcpSocket對象來和客戶端進行通信,通常通過這個函數來返回一個建立好連接的套接字。 //客戶端和服務器各有一個通信套接字,可以看出,每一方的套接字都可以獲得對方的相關信息 //接着就可以通過兩個的通信套接字來完成通信。 //取出建立好連接的套接字 tcpSocket = tcpServer->nextPendingConnection(); //獲取對方的IP和端口 QString ip = tcpSocket->peerAddress().toString(); qint16 port = tcpSocket->peerPort(); QString temp = QString("[%1:%2]:成功連接").arg(ip).arg(port); ui->textEditRead->setText(temp); //4.當一端發送成功之后,"接收方"會觸發這么一個信號,readyRead,這樣我們就能夠讀取套接字當中的內容了。 connect(tcpSocket, &QTcpSocket::readyRead, [=]() { //從通信套接字中取出內容 QByteArray array = tcpSocket->readAll(); ui->textEditRead->append(array); } ); } ); } serverWidget::~serverWidget() { delete ui; } void serverWidget::on_buttonSend_clicked() { if(NULL == tcpSocket) { return; } //獲取編輯區內容 QString str = ui->textEditWrite->toPlainText(); //給對方發送數據, 使用套接字是tcpSocket tcpSocket->write(str.toUtf8().data() ); } void serverWidget::on_buttonClose_clicked() { if(NULL == tcpSocket) { return; } //主動和客戶端端口連接 tcpSocket->disconnectFromHost(); tcpSocket->close(); tcpSocket = NULL; }
客戶端:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpSocket>//通信套接字 namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_buttonConnect_clicked(); void on_buttonSend_clicked(); void on_buttonClose_clicked(); private: Ui::Widget *ui; QTcpSocket *tcpsocket; }; #endif // WIDGET_H
#include "widget.h" #include "ui_widget.h" #include <QHostAddress> #pragma execution_character_set("utf-8") Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); tcpsocket = NULL; //0.分配空間,指定父對象 tcpsocket = new QTcpSocket(this); setWindowTitle("客戶端"); //3.連接成功之后客戶端會觸發這樣一個信號 connected connect(tcpsocket,&QTcpSocket::connected, [=]() { ui->textEditRead->setText("成功和服務器建立好鏈接"); }); connect(tcpsocket,&QTcpSocket::readyRead, [=]() { //獲取對方發送的內容 QByteArray array = tcpsocket->readAll(); //追加到編輯區中 ui->textEditRead->append(array); }); } Widget::~Widget() { delete ui; } void Widget::on_buttonConnect_clicked() { //1.獲取服務器ip和端口 QString ip = ui->lineEditIP->text(); qint16 port = ui->lineEditPort->text().toInt(); //2.主動和服務器建立鏈接 tcpsocket->connectToHost(QHostAddress(ip),port); } void Widget::on_buttonSend_clicked() { //獲取編框內容 QString str = ui->textEditWrite->toPlainText(); //發送數據 tcpsocket->write(str.toUtf8().data()); } void Widget::on_buttonClose_clicked() { //主動和對方斷開連接 tcpsocket->disconnectFromHost(); tcpsocket->close(); }