客户端与服务端的TCP通信实现(Qt)
一:TCP通信介紹
.TCP是面向連接的可靠傳輸的協議,協議規定交換的雙方必須是服務端和客戶端的兩個角色:
--- ??服務端負責監聽網絡端口,等待客戶端的連接,用連接的socket完成信息的交互;
--- ??客戶端負責每次連接的發起,建立連接后才可以進行通信;
.TCP的連接是基于流的,數據按照正確的順序存儲在接收緩沖區中,它保證數據能正確的進行交換,但不能保證數據以發送端的數據幀的形式提交。
?
?
二:界面設計
客戶端
?
?
服務端
?
?
三:客戶端編碼
?????客戶端編碼步驟如下:
(1)創建QTcpSocket套接字對象
socket = new QTcpSocket();
?
(2)使用這個對象連接服務器
//連接服務器
socket->connectToHost(IP,port);
?
(3)使用write函數向服務器發送數據
//獲取文本框的數據并以ASCII碼發送出去
void MainWindow::on_pushButton_Send_clicked()
{
? ? socket->write(ui->textEdit_Send->toPlainText().toLatin1());
? ? socket->flush();
}
?
(4)當socket接收緩沖區有新數據到來時,會發出readyRead()信號,因此為該信號添加槽函數以讀取數據。
//構造函數中連接
QObject::connect(socket,&QTcpSocket::readyRead,this,&MainWindow::socket_Read_Data);
?
void MainWindow::socket_Read_Data()
{
? ? QByteArray buffer;
? ? //讀取數據緩沖區數據
? ? buffer = socket->readAll();
?
}
?
(5)斷開與服務器的連接
//斷開連接
socket->disconnectFromHost();
?
四:服務端編碼
?????服務端編碼步驟如下:
(1)創建QTcpServer對象
server = new QTcpServer();
?
(2)偵聽一個端口,使得客戶端可以使用這個端口訪問服務器
//監聽指定的端口
if(!server->listen(QHostAddress::Any,port)){
? ?qDebug()<<server->errorString();
}
?
(3)當服務器被訪問時,會發出newConnection()信號,所以為該信號添加槽函數,并用一個QTcpSocket對象接受客戶端的訪問
//構造函數中連接
connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connection);
void MainWindow::server_New_Connection()
{
? ? //獲取客戶端的連接
? ? socket = server->nextPendingConnection();
}
?
(4)使用socket的write函數向客戶端發送數據
//客戶端有新連接是發送信號
QObject::connect(socket,&QTcpSocket::readyRead,this,&MainWindow::socket_Read_Data);
void MainWindow::socket_Read_Data()
{
? ? QByteArray buffer;
? ? //讀取數據緩沖中的數據
? ? buffer = socket->readAll();
}
?
(5)當socket接受緩沖區有新數據到來時,會發出readyRead()信號,為該信號添加槽函數
//獲取文本框數據并且以ASCII碼的形式發送
void MainWindow::on_pushButton_Send_clicked()
{
? ? socket->write(ui->textEdit_Send->toPlainText().toLatin1());
? ? socket->flush();
}
?
(6)取消偵聽
server->close();
?
?
五:修改*.pro文件
在文件中添加網絡應用的代碼庫network
QT ? ? ? += core gui network
?
?
六:中文亂碼處理
上述發送接收的代碼都是單字節數據,對于發送中文數據,在發送和接收是需要做如下處理:
發送數據:
void MainWindow::on_pushButton_Send_clicked()
{
? ? qDebug()<<"Send: "<<ui->textEdit_Send->toPlainText();
? ? //兼容中文數據發送
? ? socket->write(ui->textEdit_Send->toPlainText().toLocal8Bit());
? ? socket->flush();
? ? //獲取文本框數據并且以ASCII碼的形式發送
? ? //socket->write(ui->textEdit_Send->toPlainText().toLatin1());
? ? //socket->flush();
}
socket->write(ui->textEdit_Send->toPlainText().toLocal8Bit());
? ? socket->flush();
? ? //獲取文本框數據并且以ASCII碼的形式發送
? ? //socket->write(ui->textEdit_Send->toPlainText().toLatin1());
? ? //socket->flush();
}
接收數據:
void MainWindow::socket_Read_Data()
{
? ? QByteArray buffer;
? ? //讀取數據緩沖區數據
? ? buffer = socket->readAll();
? ? if(!buffer.isEmpty()){
? ? ? ? QString str = ui->textEdit_Recv->toPlainText();
? ? ? ? QString strRecv = QString::fromLocal8Bit(buffer);
? ? ? ? str+=strRecv+"\n";
? ? ? ? //刷新顯示
? ? ? ? ui->textEdit_Recv->setText(str);
? ? }
}
QString strRecv = QString::fromLocal8Bit(buffer);
? ? ? ? str+=strRecv+"\n";
? ? ? ? //刷新顯示
? ? ? ? ui->textEdit_Recv->setText(str);
? ? }
}
七:細節注意
?????(1)Qt5 拋棄了QTextCodec::setCodecForTr()和QTextCodec::setCodecForCString()這兩個函數。
直接將 QTextCodec::setCodecForLocale(QTextCodec::codecForName(“UTF8”)) 至于QApplication實例之前即可解決;
?????(2)本示例中,newConnection信號是對于單線程適用的,nextPendingConnection()只能用于當前線程中,當服務端面向多連接服務時,需要重載incomingConnection()方法,用socket描述符socketDescriptor定義連接socket
原文:https://blog.csdn.net/u013776188/article/details/76890094?
?
總結
以上是生活随笔為你收集整理的客户端与服务端的TCP通信实现(Qt)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCore 的代码结构
- 下一篇: 技术这东西,不可不看,不可全看.