赞
踩
常用的网络协议分为TCP和UDP两种,两种方式各有优缺点,其中TCP的主要特点是可靠,但是速度较慢(不丢包);而UDP则是不可靠传输,但速度快(可能丢包)。今天主要介绍的就是通过QT框架和TCP协议实现简单的文件传输。
QT框架中和TCP协议相关的类主要有两个
QTcpServer 和QTcpSocket
其中QTcpServer
类用来在服务器端创建服务,而QTcpSocket
用来保持客户端与服务器之间的会话。
1、首先初始化服务端设置
//初始化server
QTcpServer *server = new QTcpServer(this);
//设置监听地址和端口(设置监听来自所有地址的 对5529端口的请求)
server->listen(QHostAddress::Any,55249);
2、设置接收到请求后创建和客户端会话的socket
//QTcpServer::newConnection在有新的连接时触发,通过槽函数MainWindow::initSocket初始化socket
connect(server,&QTcpServer::newConnection,this,&MainWindow::initSocket);
void MainWindow::initSocket()
{
//QTcpServer的nextPendingConnection()返回的是新连接的socket指针 (QTcpSocket* socket)
socket = server->nextPendingConnection();
//TcpSocket::readyRead在有新数据到来时触发一次,这里表示有数据需要接收了,通过槽函数ainWindow::writefile处理获取到的数据
connect(socket,&QTcpSocket::readyRead,this,&MainWindow::writefile);
}
3、获取到数据之后进行文件的读写
void MainWindow::writefile() { //通过readAll读取socket中的数据 QByteArray data = socket->readAll(); //isFile是一个bool型变量从来表示是否是文件数据,初始值为false,因为第一次发送的数据内容为文件信息,不是文件内容 if(!isFile){ //QString的section()用来分割字符,类似于python里的切片 filename = QString(data).section("#",1,1); ui->label->setText(filename); filesize = QString(data).section("#",2,2).toInt(); receiversize = 0; file.setFileName(filename); //设置文件打开模式 if(!file.open(QIODevice::WriteOnly)) { QMessageBox::warning(this,tr("Warning"),tr("文件打开出错!")); return; } ui->progressBar->setValue(0); isFile = true; }else { //写入文件数据 qint64 lenthR = file.write(data); receiversize += lenthR; ui->progressBar->setValue(receiversize*100/filesize); } if(receiversize == filesize) { QMessageBox::warning(this,tr("Warning"),tr("文件接收完成!")); //关闭文件 file.close(); } }
客户端较服务器端简单一些,客户端只需要创建QTcpSocket
的实例化对象连接服务器即可通信。
1、初始化客户端socket
//初始化客户端socket
socket = new QTcpSocket(this);
//连接服务器
socket->connectToHost("127.0.0.1",55249,QIODevice::ReadWrite);
//观察是否连接成功
if(socket->waitForConnected(1000))
{
QMessageBox::warning(this,tr("Warning"),tr("连接成功"));
}else{
QMessageBox::warning(this,tr("Warning"),tr("连接出错"));
}
2、选择需要传输的文件,初始化文件信息
//默认打开D盘,选择图片类型的文件
QString path = QFileDialog::getOpenFileName(this,tr("open File"),"d:/",tr("Images(*.png *.jpg *.xmp)"));
//初始化文件信息
if(!path.isEmpty())file.setFileName(path);
if(file.open(QIODevice::ReadOnly))
{
QFileInfo info(path);
filename = info.fileName();
filesize = info.size();
sendsize = 0;
QMessageBox::warning(this,tr("Warning"),tr("文件加载完成"));
}
3、发送自定义文件信息以及文件内容
//使用定时器连接发送数据方法 mytimer = new QTimer(this); connect(mytimer,QTimer::timeout,this,&MainWindow::sendData); //自定义文件信息 QString buf = QString("head#%1#%2").arg(filename).arg(filesize); qint64 len = socket->write(buf.toUtf8().data()); //是否发送成功 if(len >0) { //使用定时器延时,防止粘包 mytimer->start(1000); }else{ file.close(); } void MainWindow::sendData() { qint64 len = 0; do{ //每次发送2k文件内容 char buf[2*1024] = {0}; len = file.read(buf,sizeof(buf)); len = socket->write(buf,len); sendsize+=len; qDebug()<<"SendData"; }while(len >0); if(sendsize == filesize) { QMessageBox::warning(this,tr("Warning"),tr("文件发送完毕")); socket->close(); } }
本地测试可以进行图片的传输
本实例中还存在一些问题没有修复,如每次只能发送一张图片(发送完成后不能再选择图片发送等),还有很多,因为本文只进行文件传输的简单介绍,不多赘述。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。