基于QT制作一個TCPServer與TCPClient的通信
前言
之前項目上用到了TCP通信,作為TCP的服務端上位機與下位機進行控制信號傳輸。
這篇博客就對QT中使用TCP通信理一個簡單的demo,做一個簡單的TCP服務端和客戶端的通信。
因為時間有限,這里就闡述一下基本原理和代碼實現(xiàn),具體的demo參考的是《QT5.9C++開發(fā)指南》
具體效果圖如下

1. TCP通信原理和流程闡述
1.1 TCP 通信原理簡述
TCP通信主要是三次握手和四次揮手,前者是建立連接,后者是斷開連接。

上圖是三次握手的一個基本流程圖:
首先客戶機向服務器申請同步,即向服務器申請連接。
服務器接收到請求,返回一個確認幀,告訴客戶機已經收到你的請求,同意連接。
客戶機收到同意請求信息之后,還要告訴服務器它已經收到服務器的確認請求,接下來可以傳輸數(shù)據。
上面是一個簡單的TCP建立連接的闡述,那么回歸到服務器端。在QT中,TCP服務器端使用QTcpServer用于端口監(jiān)聽和建立服務器,服務器和客戶端之間在建立連接后,通信使用QTcpSocket,套接字Socket進行。
1.2 TCP服務端建立與通信流程
在QT中,使用QTcpServer::listen()函數(shù)開始服務器端監(jiān)聽,這里可以指定監(jiān)聽的IP地址和端口。這個表示服務器的IP和端口,監(jiān)聽向這個IP和端口發(fā)起請求的客戶端。
當有新的客戶端接入時,QTcpServer內部的incomingConnection()函數(shù)會創(chuàng)建一個與客戶端連接的QTcpSocket對象,接著發(fā)射信號newConnection()。在newConnection()信號的槽函數(shù)中,可以用nextPendingConnection()接收客戶端的連接,最后使用QTcpSocket與客戶端通信。
1.3 TCP客戶端通信流程
TCP客戶端使用QTcpSocket與TCP服務器建立連接并通信。
客戶端的QTcpSocket 實例首先通過 connectToHost()嘗試連接到服務器,需要指定服務器的IP 地址和端口。
connectToHost()是異步方式連接服務器,不會阻塞程序運行,連接后發(fā)射 connected()信號。
如果需要使用阻塞方式連接服務器,則使用 waitForConnected()函數(shù)阻塞程序運行,直到連接成功或失敗。
例如:
socket->connectToHost("192.168.1.100",1340);
if(socket->waitForConnected(1000)
qDebug("Connected!");
客戶端與服務器建立socket連接后,就可以向緩沖區(qū)寫數(shù)據或從接收緩沖區(qū)讀取數(shù)據,實現(xiàn)數(shù)據的通信。當緩沖區(qū)有新數(shù)據進入時,會發(fā)射readyRead()信號,一般在此信號的槽函數(shù)里面讀取緩沖區(qū)數(shù)據。
2. 關鍵源碼闡述
2.1 服務端代碼
初始化TCP服務端,綁定信號與槽函數(shù)
QTcpServer *tcpServer; //TCP服務器
QTcpSocket *tcpSocket;//TCP通訊的Socket
tcpServer=new QTcpServer(this);
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
定義了一個TcpServer的對象tcpServer,將獲取的newConnection()信號綁定到自定義的槽函數(shù)onNewConnection()上。
開始監(jiān)聽,選擇IP和端口號
void MainWindow::on_actStart_triggered()
{//開始監(jiān)聽
QString IP=ui->comboIP->currentText();//IP地址
quint16 port=ui->spinPort->value();//端口
QHostAddress addr(IP);
tcpServer->listen(addr,port);//指定ip和端口,這里的IP就是默認IP端口也是控件的默認值端口
// tcpServer->listen(QHostAddress::LocalHost,port);// Equivalent to QHostAddress("127.0.0.1").
...
...
}
下面這個函數(shù)綁定了一些tcp連接的狀態(tài)信號和對應的處理函數(shù)。
對于接收到的tcpServer連接,使用nextPending函數(shù)創(chuàng)建socket進行通信。
void MainWindow::onNewConnection()
{
// ui->plainTextEdit->appendPlainText("有新連接");
tcpSocket = tcpServer->nextPendingConnection(); //創(chuàng)建socket
connect(tcpSocket, SIGNAL(connected()),
this, SLOT(onClientConnected()));
onClientConnected();//
connect(tcpSocket, SIGNAL(disconnected()),
this, SLOT(onClientDisconnected()));
connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
onSocketStateChange(tcpSocket->state());
connect(tcpSocket,SIGNAL(readyRead()),
this,SLOT(onSocketReadyRead()));
}
服務端發(fā)送數(shù)據函數(shù):
void MainWindow::on_btnSend_clicked()
{//發(fā)送一行字符串,以換行符結束
QString msg=ui->editMsg->text();
ui->plainTextEdit->appendPlainText("[out] "+msg);
ui->editMsg->clear();
ui->editMsg->setFocus();
QByteArray str=msg.toUtf8();
str.append('\n');//添加一個換行符
tcpSocket->write(str);
}
服務器讀取數(shù)據
void MainWindow::onSocketReadyRead()
{//讀取緩沖區(qū)行文本
// QStringList lines;
while(tcpSocket->canReadLine())
ui->plainTextEdit->appendPlainText("[in] "+tcpSocket->readLine());
// lines.append(clientConnection->readLine());
}
2.2 客戶端代碼
對于客戶端來說主要是socket通信
初始化客戶端并綁定信號
QTcpSocket *tcpClient; //socket
tcpClient=new QTcpSocket(this); //創(chuàng)建socket變量
connect(tcpClient,SIGNAL(connected()),this,SLOT(onConnected()));
connect(tcpClient,SIGNAL(disconnected()),this,SLOT(onDisconnected()));
connect(tcpClient,SIGNAL(stateChanged(QAbstractSocket::SocketState)),
this,SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
connect(tcpClient,SIGNAL(readyRead()),
this,SLOT(onSocketReadyRead()));
連接到服務器
QString addr=ui->comboServer->currentText();
quint16 port=ui->spinPort->value();
tcpClient->connectToHost(addr,port);
發(fā)送數(shù)據
void MainWindow::on_btnSend_clicked()
{//發(fā)送數(shù)據
QString msg=ui->editMsg->text();
ui->plainTextEdit->appendPlainText("[out] "+msg);
ui->editMsg->clear();
ui->editMsg->setFocus();
QByteArray str=msg.toUtf8();
str.append('\n');
tcpClient->write(str);
}
讀取數(shù)據
void MainWindow::onSocketReadyRead()
{//readyRead()信號槽函數(shù)
while(tcpClient->canReadLine())
ui->plainTextEdit->appendPlainText("[in] "+tcpClient->readLine());
}以上就是基于QT制作一個TCPServer與TCPClient的通信的詳細內容,更多關于QT TCP通信的資料請關注腳本之家其它相關文章!

