参考代码自:https://www.cnblogs.com/doker/p/11158230.html
感谢大佬的代码,我在此基础上做了些许修改,现在建立TCP
连接后,就可以一直进行文件的传输了,传输完成后不会自动断开tcp
连接。
下面是生成的exe
文件,可以直接使用。
链接:https://pan.baidu.com/s/1OZ73jGwLqxkx7BRE8h6qQw
提取码:rqyy
局域网中的两台主机,一台运行接收数据软件,一台运行发送数据软件。在发送端的文本框中输入接收端的IP
,端口不用改,默认设的8888
(服务器监听端口要在代码中改),然后点击连接端口,发送数据端会有提示,然后就可以发文件了,我设的默认的文件保存路径为E盘
下。
1、接收端代码:
(1)ui
:
(2)mainwindow.h
中:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTcpSocket>
#include <QFile>
#include <QHostAddress>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
QTcpSocket *tcpSocket; //套接字
QString fileName; //文件名字
qint64 fileSize; //文件大小
qint64 recvSize; //已经接收文件的大小
bool isStart; //接收头文件标志
QFile file; //文件对象
private:
Ui::MainWindow *ui;
private slots:
void on_buttonConnect_clicked();
void on_buttonDisConnect_clicked();
};
#endif // MAINWINDOW_H
(3)mainwindow.cpp
中:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
tcpSocket = new QTcpSocket(this);
isStart = true;
setWindowTitle(u8"数据接收端,默认端口:8888");
//设置进度条
ui->progressBar->setValue(0);
//接收到数据后触发
connect(tcpSocket,&QTcpSocket::readyRead,[=](){
//取出接收的内容
QByteArray buf = tcpSocket->readAll();
if (true == isStart)
{
//接收头
isStart = false;
// 分段 0 0 1 1 2 2
//解析头部信息 buf = "hello##1024##333333"
// QString str = "hello##1024";
// str.section("##",0,0);
//这个拆出来hello,其中##是分段标识符,格式为:段1+标识符+段2+标识符+段3+标识符+……
//初始化
fileName = QString(buf).section("##",0,0);
fileSize = QString(buf).section("##",1,1).toInt();
recvSize = 0;
//保存到E盘
file.setFileName("E:/"+fileName);
//打开文件
bool isOk = file.open(QIODevice::WriteOnly);
if (false == isOk)
{
qDebug()<<"WriteOnly error 38 ";
tcpSocket->disconnectFromHost();//断开连接
tcpSocket->close();//关闭套接字
return ;//如果打开文件失败,中断函数
}
//设置进度条
ui->progressBar->setMinimum(0);//最小值
ui->progressBar->setMaximum(fileSize/1024);//最大值
ui->progressBar->setValue(0);//当前值
}
else
{
qint64 len = file.write(buf);
if(len > 0)
{
recvSize += len;//累积接收大小
qDebug()<<len;
}
//更新进度条
ui->progressBar->setValue(recvSize/1024);
if (recvSize == fileSize)
{
//先给服务发送(接收文件完成的消息)
tcpSocket->write("file done");
QMessageBox::information(this,u8"完成",u8"文件接收完毕");
file.close();//关闭文件
//断开连接
isStart = true;
}
}
});
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(on_buttonConnect_clicked()));
connect(ui->pushButton_2,SIGNAL(clicked()),this,SLOT(on_buttonDisConnect_clicked()));
ui->pushButton_2->setEnabled(false);
ui->lineEditIP->setText("192.168.1.5");
ui->lineEditPort->setText("8888");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_buttonConnect_clicked()
{
//获取服务器的ip和端口
QString ip = ui->lineEditIP->text();
qint16 port = ui->lineEditPort->text().toInt();
tcpSocket->connectToHost(QHostAddress(ip),port);
ui->pushButton->setEnabled(false);
ui->pushButton_2->setEnabled(true);
}
void MainWindow::on_buttonDisConnect_clicked()
{
tcpSocket->disconnectFromHost();
tcpSocket->close();
ui->pushButton->setEnabled(true);
ui->pushButton_2->setEnabled(false);
}
2、数据发送端代码:
(1)ui
:
(2)mainwindow.h
中:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QFile>
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void sendData();//发送文件数据
private slots:
void on_buttonFile_clicked();
void on_buttonsend_clicked();
void close_connect();
private:
Ui::MainWindow *ui;
QTcpServer *tcpServer;//监听套接字
QTcpSocket *tcpSocket;//通信套接字
QFile file;//文件对象
QString fileName;//文件名字
qint64 fileSize;//文件大小
qint64 sendSize;//已经发送文件的大小
QTimer timer;//定时器
};
#endif // MAINWINDOW_H
(3)mainwindow.cpp
中:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//监听套接字
tcpServer = new QTcpServer(this);
//监听
tcpServer->listen(QHostAddress::Any,8888);
setWindowTitle(u8"数据发送端,默认端口:8888");
//两个按钮都不能按
ui->buttonFile->setEnabled(false);
ui->buttonsend->setEnabled(false);
//如果客户端成功和服务器连接
ui->pushButton->setEnabled(false);
connect(tcpServer,&QTcpServer::newConnection,[=](){
//取出建立好连接的套接字
tcpSocket = tcpServer->nextPendingConnection();
//获取对方的ip和端口
QString ip = tcpSocket->peerAddress().toString();
quint16 port = tcpSocket->peerPort();
QString str = QString(u8"[%1 : %2] 成功连接").arg(ip).arg(port);
//显示到编辑区
ui->textEdit->setText(str);
//成功连接后,才能按按钮
ui->buttonFile->setEnabled(true);
ui->buttonsend->setEnabled(true);
ui->pushButton->setEnabled(true);
connect(tcpSocket,&QTcpSocket::readyRead,[=](){
//取客户端信息
QByteArray buf = tcpSocket->readAll();
if (QString(buf) == "file done")
{
//文件接收完毕
file.close();
}
});
});
connect(&timer,&QTimer::timeout,[=](){
//关闭定时器
timer.stop();
//发送文件
sendData();
});
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(close_connect()));
}
MainWindow::~MainWindow()
{
delete ui;
}
//选择文件按钮
void MainWindow::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)
{
ui->textEdit->append(u8"只读方式打开文件失败");
}
//提示打开文件路径
ui->textEdit->append(filePath);
ui->buttonFile->setEnabled(true);
ui->buttonsend->setEnabled(true);
}
else
{
ui->textEdit->append(u8"选择文件路径出错");
}
}
//发送文件按钮按键
void MainWindow::on_buttonsend_clicked()
{
//先发送文件头信息 格式如:文件名##文件大小
QString head = QString("%1##%2").arg(fileName).arg(fileSize);
//发送头部的信息
qint64 len = tcpSocket->write(head.toUtf8());
qDebug()<<head;
if (len > 0)//头部信息发送成功
{
//发送真正的文件信息
//防止TCP黏包文件
//需要通过定时器延时 20ms
timer.start(20);
}
else
{
ui->textEdit->append(u8"头部信息发送失败");
file.close();
ui->buttonFile->setEnabled(true);
ui->buttonsend->setEnabled(false);
}
}
void MainWindow::sendData()
{
qint64 len = 0;
do
{
//每次发送数据的大小 4K
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(u8"文件发送完毕");
file.close();
}
}
void MainWindow:: close_connect()
{
tcpSocket->disconnectFromHost();
tcpSocket->close();
}