效果
设计步骤:
服务器端:
一、更改widget.ui文件,设计界面如下
二、打开tcpReceiver.pro添加一行代码:QT += network
三、widget.h文件内容
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtNetwork>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
QTcpServer *tcpServer;
QTcpSocket *currentClient;
qint64 totalBytes; //存放总大小信息
qint64 bytesReceived; //已收到数据的大小
qint64 fileNameSize; //文件名的大小信息
QString fileName; //存放文件名
QFile *localFile; //本地文件
QByteArray inBlock; //接收数据缓冲区
qint64 bytesWritten; //已经发送数据大小
qint64 bytesToWrite; //剩余数据大小
qint64 loadSize; //每次发送数据的大小
QByteArray outBlock; //数据缓冲区
public slots:
void NewConnection();
void recMessage();
void sendMessage();
void continueSend(qint64 numBytes);
void disconnect();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
四、widget.cpp文件内容
#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QImageReader>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
totalBytes = 0;
bytesReceived = 0;
fileNameSize = 0;
totalBytes = 0;
bytesReceived = 0;
fileNameSize = 0;
tcpServer = new QTcpServer(this);
if(!tcpServer->listen(QHostAddress::Any,6666))
{ //**本地主机的6666端口,如果出错就输出错误信息,并关闭
qDebug() << tcpServer->errorString();
close();
}
//连接信号和相应槽函数,有新的连接进入是需处理
connect(tcpServer,SIGNAL(newConnection()),this,SLOT(NewConnection()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::NewConnection()
{
//新连接进入的显示处理
currentClient = tcpServer->nextPendingConnection();
ui->label_2->setText(tr("%1:%2").arg(currentClient->peerAddress().toString().split("::ffff:")[1])\
.arg(currentClient->peerPort()));
connect(currentClient, SIGNAL(readyRead()), this, SLOT(recMessage()));
connect(currentClient, SIGNAL(disconnected()), this, SLOT(disconnect()));
}
void Widget::recMessage()
{
QDataStream in(currentClient);
in.setVersion(QDataStream::Qt_5_8);
if(bytesReceived <= sizeof(qint64)*2)
{ //如果接收到的数据小于16个字节,那么是刚开始接收数据,我们保存到//来的头文件信息
if((currentClient->bytesAvailable() >= sizeof(qint64)*2)
&& (fileNameSize == 0))
{ //接收数据总大小信息和文件名大小信息
in >> totalBytes >> fileNameSize;
bytesReceived += sizeof(qint64) * 2;
}
if((currentClient->bytesAvailable() >= fileNameSize)
&& (fileNameSize != 0))
{ //接收文件名,并建立文件
in >> fileName;
ui->label_2->setText(tr("接收文件 %1 ...").arg(fileName));
bytesReceived += fileNameSize;
ui->label_2->setText(fileName);
localFile= new QFile(fileName);
if(!localFile->open(QFile::WriteOnly))
{
qDebug() << "open file error!";
return;
}
}
else return;
}
if(bytesReceived < totalBytes)
{ //如果接收的数据小于总数据,那么写入文件
bytesReceived += currentClient->bytesAvailable();
inBlock+= currentClient->readAll();
}
//更新进度条
ui->progressBar->setMaximum(totalBytes);
ui->progressBar->setValue(bytesReceived);
if(bytesReceived == totalBytes)
{ //接收数据完成时
//接收显示
QBuffer buffer(&inBlock);
buffer.open(QIODevice::ReadOnly);
QImageReader reader(&buffer,"png");
QImage image = reader.read();
if(!image.isNull())
{
image=image.scaled(ui->label_3->size());
ui->label_3->setPixmap(QPixmap::fromImage(image));
}
localFile->write(inBlock);
localFile->close();
inBlock.resize(0);
//重新置0 准备下次接收
totalBytes = 0;
bytesReceived = 0;
fileNameSize = 0;
ui->label_2->setText(tr("接收文件 %1 成功!").arg(fileName));
}
}
void Widget::disconnect()
{
qDebug()<<"disconnect";
}
客端户:
一、更改widget.ui文件,设计界面如下
二、打开tcpSender.pro添加一行代码:QT += network
三、widget.h文件内容
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QtNetwork>
#include <QImageReader>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
QTcpSocket *tcpSocket;
QFile *localFile; //要发送的文件
qint64 totalBytes; //数据总大小
qint64 bytesWritten; //已经发送数据大小
qint64 bytesToWrite; //剩余数据大小
qint64 loadSize; //每次发送数据的大小
QString fileName; //保存文件路径
QByteArray outBlock; //数据缓冲区,即存放每次要发送的数据
QByteArray inBlock; //数据缓冲区,接收
qint64 bytesReceived; //已收到数据的大小
qint64 fileNameSize; //文件名的大小信息
public slots:
void newConnect(); //连接服务器
void readData(); //接收数据
void sendData();//发送数据
void continueSend(qint64 numBytes); //继续并更新发送进度条
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
四、widget.cpp文件内容
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
tcpSocket = new QTcpSocket(this);
loadSize = 4*1024;
totalBytes = 0;
bytesWritten = 0;
bytesToWrite = 0;
//接收
bytesReceived = 0;
fileNameSize = 0;
//当有数据发送成功时,继续发送
connect(tcpSocket,SIGNAL(bytesWritten(qint64)),this,SLOT(continueSend(qint64)));
ui->pushButton_2->setEnabled(false);
}
Widget::~Widget()
{
delete ui;
}
void Widget::newConnect()
{
// blockSize = 0; //初始化其为0
tcpSocket->abort(); //取消已有的连接
//连接到主机,这里从界面获取主机地址和端口号
tcpSocket->connectToHost(ui->lineEdit->text(), ui->lineEdit_2->text().toInt());
ui->pushButton_2->setEnabled(true);
}
void Widget::sendData()
{
bytesWritten = 0;
fileName = QFileDialog::getOpenFileName(this);
if(!fileName.isEmpty())
{
localFile = new QFile(fileName);
if(!localFile->open(QFile::ReadOnly))
{
qDebug() << "open file error!";
return;
}
//文件总大小
totalBytes = localFile->size();
QDataStream sendOut(&outBlock,QIODevice::WriteOnly);
sendOut.setVersion(QDataStream::Qt_5_8);
QString currentFileName = fileName.right(fileName.size()
- fileName.lastIndexOf('/')-1);
//依次写入总大小信息空间,文件名大小信息空间,文件名
sendOut << qint64(0) << qint64(0) << currentFileName;
//这里的总大小是文件名大小等信息和实际文件大小的总和
totalBytes += outBlock.size();
sendOut.device()->seek(0);
//返回outBolock的开始,用实际的大小信息代替两个qint64(0)空间
sendOut<<totalBytes<<qint64((outBlock.size() - sizeof(qint64)*2));
//发送完头数据后剩余数据的大小
bytesToWrite = totalBytes - tcpSocket->write(outBlock);
ui->label_4->setText(tr("开始发送"));
outBlock.resize(0);
}
}
void Widget::continueSend(qint64 numBytes)
{
//已经发送数据的大小
qDebug()<<"numBytes"<<numBytes;
bytesWritten += (int)numBytes;
if(bytesToWrite > 0) //如果已经发送了数据
{
//每次发送loadSize大小的数据,这里设置为4KB,如果剩余的数据不足4KB,
//就发送剩余数据的大小
outBlock = localFile->read(qMin(bytesToWrite,loadSize));
//发送完一次数据后还剩余数据的大小
bytesToWrite -= (int)tcpSocket->write(outBlock);
//清空发送缓冲区
outBlock.resize(0);
} else {
localFile->close(); //如果没有发送任何数据,则关闭文件
}
//更新进度条
ui->progressBar->setMaximum(totalBytes);
ui->progressBar->setValue(bytesWritten);
if(bytesWritten == totalBytes) //发送完毕
{
ui->label_4->setText(tr("传送文件 %1 成功").arg(fileName));
localFile->close();
}
}
void Widget::on_pushButton_clicked()
{
newConnect();
}
void Widget::on_pushButton_2_clicked()
{
sendData();
}
版权声明:本文为qq_34623621原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。