赞
踩
UDP协议单次传输文件不能超过512字节,否则UDP数据包在IP曾需要拆分再重组,很容易出错。
我们采取的办法是将需要传输的文件进行组包:服务器端组包,一个包由228字节的数据和28字节的包头组成,包头包含了数据的所有信息和客户端的接收方法。客户端从数据包中提取数据进行存储。
百度网盘分享代码
链接:https://pan.baidu.com/s/1cwcAH4ugobYqQ0c4UYdCiw
提取码:1234
代码使用的注意事项:
1.这个代码的UI没什么用处,因为对于发送端来说,对方的port是在代码指定的,只需要一个发送按钮就可以,接收方监听的端口也已经在代码指定。
2.需要修改的地方:
(1)服务器端代码:QFile file("D:\\3.ts");需要发送什么文件,就怎么写它的绝对路径。
(2)客户端代码:把file.setFileName("3.ts")里的3.ts修改为你想保存的文件名和格式。
1.服务器端代码
- #include "server.h"
- #include "ui_server.h"
- #include <QTime>
- #include <QDesktopWidget>
- #include<QDebug>
- #include<QFileInfo>//获取文件信息
- server::server(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::server)
- {
- ui->setupUi(this);
- m_udpSocket = new QUdpSocket(this);
- sendsize=0;
- m_udpSocket->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption,8*1024*1024);
- m_udpSocket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,500000);
-
- }
-
- server::~server()
- {
- delete ui;
- }
-
-
- void server::on_pushButton_clicked()
- {
- //while(1) {
- // QPixmap result = QPixmap();
- // result = QPixmap::grabWindow(QApplication::desktop()->winId(), 0, 0, 800, 600); //抓取当前屏幕的图片
-
- // result.save("D:\\LX\\Work\\Project\\802PC\\TcpServetTest\\802TCPServer\\eee.jpg");
- QFile file("D:\\3.ts");
- if (!file.open(QIODevice::ReadOnly))return;
- //包1024=包头28(7个整形)+数据(996)
- char *m_sendBuf = new char[1024];
- //size:文件大小
- int size = file.size();
- qDebug()<<"文件大小"<<size;
- //num:数据包数量
- int num = 0;
- //count:数据包序号
- int count = 0;
- //最后一个包的大小
- int endSize = size%996;
- if (endSize == 0) {
- num = size/996;
- }
- else {
- num = size/996+1;//num:包的数量
- }
- qint64 len = 0;//记录发送数据
-
- // //一、发送文件信息
- // //1.获取文件路径
- // QString filepath = "D:/3.ts";
- // //2.获取文件信息
- // QFileInfo info(filepath);
- // fileName = info.fileName();
-
- // fileSize = info.size();
- // //3.设置文件名
- // file.setFileName(filepath);
-
- //二、发送数据
- //1、组包:28字节包头+996字节数据
- //2、发送:广播到port:65522
- while (count < num) {
- //初始化:将m_sendBuf的前1024个字符置0
- memset(m_sendBuf, 0, 1024);
- //包的结构体
- ImageFrameHead mes;
- //功能码24
- mes.funCode = 24;
- //包头长度=4*7=28
- mes.uTransFrameHdrSize = sizeof(ImageFrameHead);
- if ((count+1) != num) {
- //数据长度
- mes.uTransFrameSize = 996;
-
- }
- else {
- //最后一个包的长度
- mes.uTransFrameSize = endSize;
- }
- //qDebug()<<size;
- //数据帧总大小=文件大小
- mes.uDataFrameSize = size;
- //包个数
- mes.uDataFrameTotal = num;
- //包序号
- mes.uDataFrameCurr = count+1;
- //数据996的整数倍
- mes.uDataInFrameOffset = count*(1024 - sizeof(ImageFrameHead));
- qDebug()<<"uDataInFrameOffset"<<mes.uDataInFrameOffset;
- //读取文件,参数1:存储位置——指针,参数2:maxsize
- //参数1:意思是指向m_sendBuf向后移28位的位置,将996位的数据存在这里
- //从文件里读取996字节数据写入m_sendBuf数据包里数据的位置
- // data:file(996字节)->m_sendBuf(29字节起-1024字节)
- len = file.read(m_sendBuf+sizeof(ImageFrameHead), 1024-sizeof(ImageFrameHead));
- sendsize+=len;
- qDebug()<<"已发送文件大小"<<sendsize;
- //从mes里复制28个字节给m_sendBuf,mes:包头结构体。
- //构建包:m_sendBuf的前28字节写包的信息。
- memcpy(m_sendBuf, (char *)&mes, sizeof(ImageFrameHead));
- //发数据:m_sendBuf即包。
- //参数2:包的长度=表头+数据=1024,最后一个包不一定
- m_udpSocket->writeDatagram(m_sendBuf, mes.uTransFrameSize+mes.uTransFrameHdrSize, QHostAddress("224.0.0.10"), 65522);
- //currentTime:返回当前时间
- //addMSecs:返回QTime对象dieTime,其时间比当前时间延后1ms
- //dieTime = 当前时间 + 1ms
- QTime dieTime = QTime::currentTime().addMSecs(1);
- //防止卡死,隔一段时间检查有没有未完成操作
- while( QTime::currentTime() < dieTime )
- QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
- count++;
- }
- qDebug()<<"数据发送完成";
- file.close();
- QTime dieTime = QTime::currentTime().addMSecs(10);
- while( QTime::currentTime() < dieTime )
- QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
- //qDebug("ok");
- }
-
-
- //}
2.客户端代码
- #include "client.h"
- #include "ui_client.h"
-
-
-
- client::client(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::client)
- {
- ui->setupUi(this);
- m_udpThread = new UdpThread(this);
- //sigRecvok:线程完成——读取结束的信号
- //信号传来了数据char
- connect(m_udpThread, SIGNAL(sigRecvOk(char*,int)), this, SLOT(slotRecv_client(char*,int)));
- m_udpThread->start();
- qDebug("OK");
-
- }
-
- client::~client()
- {
- delete ui;
- }
-
- void client::slotRecv_client(char * buf, int len)
- {
- file.setFileName("3.ts");
- filesize = len;
- file.resize(filesize);
-
- bool isOK = file.open(QIODevice::WriteOnly);//isOK:文件成功打开标志
-
- qDebug()<<isOK;
- qint64 write_len=file.write(buf,len);
-
- qDebug()<<"client:写入文件的大小"<<write_len;
- qDebug()<<"filesize="<<len;
-
- QPixmap pixmap;
- pixmap.loadFromData((uchar*)buf, len, "ts");
- ui->label->setPixmap(pixmap);
- file.close();
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。