客户端与服务端的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
相关文章
- Qt-QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connect...
- QT-Qt界面居中显示
- s3c2410上搭建QT/Embedded4.8.5开发环境(七)--命令行开始第一个Qt程序
- Qt音视频开发21-mpv内核万能属性机制
- Qt音视频开发6-ffmpeg解码处理
- Qt编写自定义控件15-百分比仪表盘
- Qt编写linux上视频流播放器(支持海康大华宇视等各种网络摄像机)
- Qt编写安防视频监控系统50-地图配置
- Qt开源作品11-屏幕录制控件
- Qt之QGraphicsView进阶篇
- Qt中的内存泄漏
- Qt硬件序列号
- Qt GraphicsView框架
- Qt 读取csv文件并且绘制折线图
- Qt TCP/IP(多客户端连接服务器)多个客户端同时登陆的聊天室示例
- Qt 内省机制探析
- Qt自定义进度条
- Qt开发-QT Widgets
- 2、QT基础——创建Qt项目
- 1、QT基础——Qt概述
- qt各种版本下载地址
- Qt5Gui!QRasterPaintEngine::penChanged QT程序崩溃
- QT案例实战1 - 从零开始编写一个OCR工具软件 (9) 使用QTcpServer建立一个Tcp服务端
- QT案例实战1 - 从零开始编写一个OCR工具软件 (1)简述
- Qt数据库应用3-数据打印到pdf