生活随笔
收集整理的這篇文章主要介紹了
Qt的Socket通信
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Qt的Socket通信
文章目錄
- Qt的Socket通信
- 1 TCP/IP
- 2. UDP
- 3. TCP/IP 和 UDP的區別
Qt中提供的所有的Socket類都是非阻塞的。
Qt中常用的用于socket通信的套接字類:
用于TCP/IP通信, 作為服務器端套接字使用
用于TCP/IP通信,作為客戶端套接字使用。
用于UDP通信,服務器,客戶端均使用此套接字。
1 TCP/IP
在Qt中實現TCP/IP服務器端通信的流程:
- 創建套接字
- 將套接字設置為監聽模式
- 等待并接受客戶端請求
可以通過QTcpServer提供的void newConnection()信號來檢測是否有連接請求,如果有可以在對應的槽函數中調用nextPendingConnection函數獲取到客戶端的Socket信息(返回值為QTcpSocket*類型指針),通過此套接字與客戶端之間進行通信。 - 接收或者向客戶端發送數據
- 接收數據:使用read()或者readAll()函數
- 發送數據:使用write()函數
客戶端通信流程:
- 創建套接字
- 連接服務器
- 可以使用QTcpSocket類的connectToHost()函數來連接服務器。
- 向服務器發送或者接受數據
下面例子為簡單的TCP/IP通信的實現:
服務器端
通過Qt提供的QTcpServer類實現服務器端的socket通信:
class TCPServer : public QMainWindow
{Q_OBJECT
public:explicit TCPServer(QWidget
*parent
= 0);~TCPServer();public slots
:void slotNewConnection();void slotReadyRead();private:Ui
::TCPServer
*ui
;QTcpServer
* m_server
;QTcpSocket
* m_client
;
};
TCPServer
::TCPServer(QWidget
*parent
) :QMainWindow(parent
),ui(new Ui
::TCPServer
),m_server(NULL),m_client(NULL)
{ui
->setupUi(this);m_server
= new QTcpServer(this);m_server
->listen(QHostAddress
::Any
, 9999);connect(m_server
, &QTcpServer
::newConnection
,
this, &TCPServer
::slotNewConnection
);
}TCPServer
::~TCPServer()
{delete ui
;
}void TCPServer
::slotNewConnection()
{if(m_client
== NULL){m_client
= m_server
->nextPendingConnection();m_client
->write("服務器連接成功!!!");connect(m_client
, &QTcpSocket
::readyRead
, this, &TCPServer
::slotReadyRead
);}
}void TCPServer
::slotReadyRead()
{QByteArray array
= m_client
->readAll();QMessageBox
::information(this, "Client Message", array
);
}
客戶端
客戶端通過使用Qt提供的QTcpSocket類可以方便的實現與服務器端的通信。
class TCPClient : public QMainWindow
{Q_OBJECT
public:explicit TCPClient(QWidget
*parent
= 0);~TCPClient();public slots
:void slotReadyRead();void slotSendMsg();private:Ui
::TCPClient
*ui
;QTcpSocket
* m_client
;};
TCPClient
::TCPClient(QWidget
*parent
) :QMainWindow(parent
),ui(new Ui
::TCPClient
)
{ui
->setupUi(this);m_client
= new QTcpSocket(this);m_client
->connectToHost(QHostAddress("127.0.0.1"), 9999);connect(m_client
, &QTcpSocket
::readyRead
,
this, &TCPClient
::slotReadyRead
);connect(ui
->btnSend
, &QPushButton
::clicked
,
this, &TCPClient
::slotSendMsg
);
}TCPClient
::~TCPClient()
{delete ui
;
}void TCPClient
::slotReadyRead()
{QByteArray array
= m_client
->readAll();QMessageBox
::information(this, "Server Message", array
);
}void TCPClient
::slotSendMsg()
{QString text
= ui
->textEdit
->toPlainText();m_client
->write(text
.toUtf8());ui
->textEdit
->clear();
}
2. UDP
使用Qt提供的QUdpSocket進行UDP通信。在UDP方式下,客戶端并不與服務器建立連接,它只負責調用發送函數向服務器發送數據。類似的服務器也不從客戶端接收連接,只負責調用接收函數,等待來自客戶端的數據的到達。
在UDP通信中,服務器端和客戶端的概念已經顯得有些淡化,兩部分做的工作都大致相同:
- 創建套接字
- 綁定套接字
在UDP中如果需要接收數據則需要對套接字進行綁定,只發送數據則不需要對套接字進行綁定。 - 通過調用bind()函數將套接字綁定到指定端口上。
- 接收或者發送數據
- 接收數據:使用readDatagram()接收數據,函數聲明如下:
qint64
readDatagram(char * data
, qint64 maxSize
,
QHostAddress
* address
= 0, quint16
* port
= 0)參數
:
data
: 接收數據的緩存地址
maxSize
: 緩存接收的最大字節數
address
: 數據發送方的地址(一般使用提供的默認值)
port
: 數據發送方的端口號(一般使用提供的默認值)
使用
pendingDatagramSize()可以獲取到將要接收的數據的大小,
根據該函數返回值來準備對應大小的內存空間存放將要接收的數據。
- 發送數據: 使用writeDatagram()函數發送數據,函數聲明如下:
qint64
writeDatagram(const QByteArray
& datagram
,
const QHostAddress
& host
, quint16 port
)參數:
datagram:要發送的字符串
host:數據接收方的地址
port:數據接收方的端口號
#include "widget.h"
#include "ui_widget.h"
#include <QHostAddress>Widget
::Widget(QWidget
*parent
) :QWidget(parent
),ui(new Ui
::Widget
)
{ui
->setupUi(this);udpsocket
= new QUdpSocket(this);udpsocket
->bind(9090);setWindowTitle("server port is 9090");connect(udpsocket
,&QUdpSocket
::readyRead
,[=](){char buf
[1024] = {0};QHostAddress clientaddr
;quint16 clientport
;quint64 size
= udpsocket
->readDatagram(buf
,sizeof(buf
),&clientaddr
,&clientport
);if(size
> 0){QString str
= QString("[%1 : %2] : %3").arg(clientaddr
.toString()).arg(clientport
).arg(buf
);ui
->textEdit
->append(str
);}});
}Widget
::~Widget()
{delete ui
;
}void Widget
::on_ButtonSend_clicked()
{QString ip
= ui
->lineEditIP
->text();quint16 port
= ui
->lineEditPort
->text().toInt();QString str
= ui
->textEdit
->toPlainText();udpsocket
->writeDatagram(str
.toUtf8(),QHostAddress(ip
),port
);
}
廣播
- 在使用QUdpSocket類的writeDatagram()函數發送數據的時候,其中第二個參數host應該指定為廣播地址:QHostAddress::Broadcast此設置相當于QHostAddress(“255.255.255.255”)
- 使用UDP廣播的的特點:
- 使用UDP進行廣播,局域網內的其他的UDP用戶全部可以收到廣播的消息
- UDP廣播只能在局域網范圍內使用
組播
- 我們再使用廣播發送消息的時候會發送給所有用戶,但是有些用戶是不想接受消息的,這時候我們就應該使用組播,接收方只有先注冊到組播地址中才能收到組播消息,否則則接受不到消息。另外組播是可以在Internet中使用的。
在使用QUdpSocket類的writeDatagram()函數發送數據的時候,其中第二個參數host應該指定為組播地址,關于組播地址的分類:
- 224.0.0.0~224.0.0.255為預留的組播地址(永久組地址),地址224.0.0.0保留不做分配,其它地址供路由協議使用;
- 224.0.1.0~224.0.1.255是公用組播地址,可以用于Internet;
- 224.0.2.0~238.255.255.255為用戶可用的組播地址(臨時組地址),全網范圍內有效;
- 239.0.0.0~239.255.255.255為本地管理組播地址,僅在特定的本地范圍內有效。
注冊加入到組播地址需要使用QUdpSocket類的成員函數:
bool joinMulticastGroup(const QHostAddress
& groupAddress
)
3. TCP/IP 和 UDP的區別
總結
以上是生活随笔為你收集整理的Qt的Socket通信的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。