Qt---TCP文件传输服务器

文件传输流程:

 服务器端:

serverwidget.ui

serverwidget.h

#ifndef SERVERWIDGET_H
#define SERVERWIDGET_H#include <QWidget>
#include<QTcpServer>//监听套接字
#include<QTcpSocket>//通信套接字
#include<QFile>
#include<QTimer>QT_BEGIN_NAMESPACE
namespace Ui { class ServerWidget; }
QT_END_NAMESPACEclass ServerWidget : public QWidget
{Q_OBJECTpublic:ServerWidget(QWidget *parent = nullptr);~ServerWidget();void sendData();//发送文件数据private slots:void on_buttonFile_clicked();void on_buttonSend_clicked();private:Ui::ServerWidget *ui;QTcpServer *tcpServer;//监听套接字QTcpSocket *tcpSocket;//通信套接字QFile file;//文件对象QString fileName;//文件名字qint64 fileSize;//文件大小qint64 sendSize;//已经发送文件大小QTimer timer;//定时器};
#endif // SERVERWIDGET_H

serverwidget.cpp

#include "serverwidget.h"
#include "ui_serverwidget.h"
#include<QFileDialog>
#include<QDebug>
#include<QFileInfo>
#include<QTimer>ServerWidget::ServerWidget(QWidget *parent): QWidget(parent), ui(new Ui::ServerWidget)
{ui->setupUi(this);//监听套接字tcpServer = new QTcpServer(this);//监听tcpServer->listen(QHostAddress::Any,8888);setWindowTitle("服务器端口为:8888");//两个按钮都不能按ui->buttonFile->setEnabled(false);ui->buttonSend->setEnabled(false);//如果客户端成功和服务器连接//tcpServer会自动触发newConnection()connect(tcpServer,&QTcpServer::newConnection,[=](){//取出建立好连接的套接字tcpSocket = tcpServer->nextPendingConnection();//获取对方的IP和端口QString ip = tcpSocket->peerAddress().toString();quint16 port = tcpSocket->peerPort();QString str = QString("[%1:%2] 成功连接").arg(ip).arg(port);ui->textEdit->setText(str);//显示到编辑区//成功连接后,才能选择文件ui->buttonFile->setEnabled(true);});connect(&timer,&QTimer::timeout,[=](){//关闭定时器timer.stop();//发送文件sendData();});}ServerWidget::~ServerWidget()
{delete ui;
}//选择文件按钮
void ServerWidget::on_buttonFile_clicked()
{QString filePath = QFileDialog::getOpenFileName(this,"open","../");if(false == filePath.isEmpty())//如果选择文件路径有效{fileName.clear();fileSize = 0;//获取文件信息QFileInfo info(filePath);fileName = info.fileName();//获取文件名字fileSize = info.size();//获取文件大小sendSize = 0;//发送文件的大小//只读方式打开//指定文件的名字file.setFileName(filePath);//打开文件bool isOK = file.open(QIODevice::ReadOnly);if(false == isOK){qDebug()<<"只读的方式打开文件失败 77";}//提示打开文件的路径ui->buttonFile->setEnabled(false);ui->buttonSend->setEnabled(true);}else{qDebug()<<"选择文件路径出错 62";}}
//发送文件按钮
void ServerWidget::on_buttonSend_clicked()
{//先发送文件头信息QString head = QString("%1##%2").arg(fileName).arg(fileSize);//发送头部信息qint64 len = tcpSocket->write(head.toUtf8());if(len > 0)//头部信息发送成功{//发送真正的文件信息//防止TCP黏包问题//需要通过定时器延时20 mstimer.start(20);}else{qDebug()<<"头部信息发送失败 110";file.close();ui->buttonFile->setEnabled(true);ui->buttonSend->setEnabled(false);}
}void ServerWidget::sendData()
{qint64 len = 0;do{char buf[4*1024] = {0};len = 0;//往文件在读数据len = file.read(buf,sizeof(buf));//发送数据,读多少,发多少len = tcpSocket->write(buf,len);//发送的数据需要积累sendSize += len;}while(len > 0);//是否发送文件完毕if(sendSize == fileSize){ui->textEdit->append("文件发送完毕");file.close();//把客户端挂关闭tcpSocket->disconnectFromHost();tcpSocket->close();}
}

客户端:

main.cpp

#include "serverwidget.h"
#include"clientwidget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);ServerWidget w;w.show();ClientWidget w2;w2.show();return a.exec();
}

clientwidget.ui

clientwidget.h

#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H#include <QWidget>
#include<QTcpSocket>//通信套接字
#include<QFile>namespace Ui {
class ClientWidget;
}class ClientWidget : public QWidget
{Q_OBJECTpublic:explicit ClientWidget(QWidget *parent = nullptr);~ClientWidget();private slots:void on_pushButton_clicked();private:Ui::ClientWidget *ui;QTcpSocket *tcpSocket;//通信套接字QFile file;//文件对象QString fileName;//文件名字qint64 fileSize;//文件大小qint64 recvSize;//已经接收文件大小bool isStart;
};#endif // CLIENTWIDGET_H

clientwidget.cpp

#include "clientwidget.h"
#include "ui_clientwidget.h"
#include<QDebug>
#include<QMessageBox>
#include<QHostAddress>ClientWidget::ClientWidget(QWidget *parent) :QWidget(parent),ui(new Ui::ClientWidget)
{ui->setupUi(this);tcpSocket = new QTcpSocket(this);isStart = true;connect(tcpSocket,&QTcpSocket::readyRead,[=](){//取出接收的内容QByteArray buf = tcpSocket->readAll();if(true == isStart){//接收头isStart = false;//解析头部信息 QString buf = "hello##1024"
//            QString str = "hello##1024##mike";
//            str.section("##",0,0);//以##进行拆分//初始化fileName = QString(buf).section("##",0,0);fileSize = QString(buf).section("##",1,1).toInt();recvSize = 0;//打开文件file.setFileName(fileName);bool isOK = file.open(QIODevice::WriteOnly);if(false == isOK){qDebug()<<"WriteOnly error 40";}}else//文件信息{qint64 len = file.write(buf);recvSize  += len;if(recvSize == fileSize){file.close();QMessageBox::information(this,"完成","文件接收完成");tcpSocket->disconnectFromHost();tcpSocket->close();}}});}ClientWidget::~ClientWidget()
{delete ui;
}void ClientWidget::on_pushButton_clicked()
{//获取服务器的IP和端口QString ip = ui->lineEditIP->text();quint16 port = ui->lineEditPort->text().toInt();tcpSocket->connectToHost(QHostAddress(ip),port);
}

输出如下所示:

在当前目录下可找到传输的文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/706222.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动手学深度学习20 卷积层里的填充和步幅

动手学深度学习20 卷积层里的填充和步幅 1. 填充和步幅2. 代码实现3. QA4. 练习 课本&#xff1a; https://zh-v2.d2l.ai/chapter_convolutional-neural-networks/padding-and-strides.html 1. 填充和步幅 卷积网络可调的超参数。 当输入shape一定&#xff0c;卷积核shape一定&…

13GBDT特征交叉

GBDT特征交叉 学习目标 知道如何使用GBDT进行特征交叉1. GBDT特征衍生简介 在风控领域发展过程中,使用最多的方法是逻辑回归,逻辑回归使用了sigmoid变换将函数值映射到[0,1]区间,映射后的函数值就是对一个人违约概率的预估值。逻辑回归同样属于广义线性模型,容易并行化,…

GPT5 如何使用?GPT5 如何订阅?GPT5 功能全面详解

结论是&#xff1a;GPT2 很糟糕 &#xff0c;GPT3 很糟糕 &#xff0c;GPT4 可以 &#xff0c;但 GPT5 会很好。 ChatGPT5今年发布 GPT5发布的具有推理功能的不断发展&#xff0c;就像 iPhone 一样。 Sam Altman 于 17 日&#xff08;当地时间&#xff09;&#xff0c;在世界…

Python函数之旅专栏(导航)

Python内置函数(参考版本:3.11.8)AELRabs( )enumerate( )len( )range( )aiter( )eval( )list( )repr( )all( )exec( )locals( )reversed( )anext( )round( )any( ) ascii( )FM  filter( )map( )S float( )max( )set( )Bformat( )memoryview( )setattr( )bin( )frozenset( )…

初识C语言——第二十一天

猜数字小游戏的实现&#xff1a; 学会了之后可以自己制作彩票抽奖&#xff0c;哈哈&#xff01; 代码实现&#xff1a; #include <stdlib.h> #include <time.h>void menu()//无返回值函数 {printf("**************************\n");printf("****…

Elasticsearch的并发控制策略

文章目录 利用external对版本号进行外部控制利用if_seq_no和if_primary_term作为唯一标识来避免版本冲突 ES中的文档是不可变更的。如果你更新一个文档,会将就文档标记为删除,同时增加一个全新的文档。同时文是的version字段加1内部版本控制 If_seq_no If_primary_term 使用外…

食堂供餐 - 二分查找

系列文章目录 文章目录 系列文章目录前言一、题目描述二、输入描述三、输出描述四、补充说明四、java代码五、测试用例 前言 本人最近再练习算法&#xff0c;所以会发布自己的解题思路&#xff0c;希望大家多指教 一、题目描述 某公司员工食堂以盒饭的方式供餐。 为将员工取…

【GESP试卷】2024年03月Scratch三级试卷

2024年GESP03月认证Scratch三级试卷 分数&#xff1a;100 题数&#xff1a;27 一、单选题(共15题&#xff0c;每题2分&#xff0c;共30分) 010203040506070809101112131415CBACADDADCBCBAB 1、小杨的父母最近刚刚给他买了一块华为手表&#xff0c;他说手表上跑的是鸿蒙&…

Java刷题-基础篇

目录 题目1&#xff1a;改变原有数组元素的值 题目2&#xff1a;奇数位于偶数之前 题目3&#xff1a;两数之和 题目4&#xff1a;只出现一次的数字 题目5&#xff1a;多数元素 题目6&#xff1a;存在连续三个奇数的数组 题目1&#xff1a;改变原有数组元素的值 题目详细…

C++基础与函数解析 | 函数的声明与定义 | 函数调用 | 函数详解 | 函数重载 | 重载解析 | 递归函数 | 内联函数 | 函数指针

文章目录 一、函数基础1.基本函数定义2.函数的声明与定义3.函数调用 二、函数详解1.参数2.函数体3.返回类型 三、函数重载与重载解析1.函数重载2.重载解析 四、函数相关的其他内容1.递归函数2.内联函数3.constexpr函数&#xff08;C11起&#xff09;4.consteval 函数 (C20 起 )…

什么是直接内存(NIO)

直接内存不受 JVM 内存回收管理&#xff0c;是虚拟机的系统内存&#xff0c;常见于 NIO 操作时&#xff0c;用于数据 缓冲区&#xff0c;分配回收成本较高&#xff0c;但读写性能高&#xff0c;不受 JVM 内存回收管理。 举例 当上传一个较大文件&#xff08;200M&#xff09;…

构建智能电子商务系统:数字化引领未来商业发展

随着互联网技术的飞速发展和消费者行为的变革&#xff0c;电子商务系统的重要性日益凸显。在这一背景下&#xff0c;构建智能电子商务系统成为推动商业数字化转型的关键举措。本文将深入探讨智能电子商务系统的构建与优势&#xff0c;助力企业把握数字化转型的主动权。 ### 智…