分为服务器和客户端
下面来具体贴出代码。 每一句的具体注释都在,帮助理解:
先贴 客户端
首先在项目文件 .pro中添加 network
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QtcpSocket> #include<QFileDialog> #include<QFileInfo> #include<QTimer> #include<QFile> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_connectBtn_clicked(); void connectedSlot(); void on_openBtn_clicked(); void on_uploadBtn_clicked(); void sendFileSlot(); private: Ui::Widget *ui; QTcpSocket *socket; QString filePath; QString fileName; int fileSize; QTimer timer; }; #endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("客户端");
socket = new QTcpSocket(this);
connect(socket,SIGNAL(connected()),this,SLOT(connectedSlot()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::connectedSlot()
{
ui->connectBtn->setEnabled(false);
}
void Widget::on_connectBtn_clicked()
{
socket->connectToHost("192.168.0.111",8888);
}
//打开文件按钮的槽函数 作用是得到文件,并显示文件信息
void Widget::on_openBtn_clicked()
{
//获得文件路径,并且判断是否为空
filePath = QFileDialog::getOpenFileName(this,"open","./","ALL(*.*)");
if(filePath.isEmpty())
{
return;
}
//接下来得到文件信息,使用QFileInfo
QFileInfo info(filePath);
fileName = info.fileName();
fileSize = info.size();
ui->textBrowser->append("要上传的文件为:"+fileName);
}
//发送文件 按钮的槽函数的功能是 发送文件名和文件大小。
void Widget::on_uploadBtn_clicked()
{
// 我们可以 先发送 文件名和文件大小,然后定时器停顿几秒,
//然后开始发送文件,这样的话可以有效的吧文件区分开来,
//可以 做一个timeout 信号 来开始发送文件,完美。
QString headInfo = fileName+ "##" +QString::number(fileSize);
QByteArray arr;
arr.append(headInfo);
//因为下面的参数类型是 QByteArray 所以在上面需要定义一个arr;
socket->write(arr);
timer.start(100);
//接下来连接timeout 信号和槽函数
connect(&timer,SIGNAL(timeout()),this,SLOT(sendFileSlot()));
}
// 接下来来实现 发送文件的 槽函数
//接收到 timeout信号以后 开始发送文件
void Widget::sendFileSlot()
{
timer.stop();
//开始发送文件内容
QFile file(filePath);
bool ok = file.open(QIODevice::ReadOnly);
if(true == ok)
{
QByteArray arr = file.readAll();
qint64 ret = socket->write(arr);
if( fileSize==ret)
{
ui->textBrowser->append("文件上传成功!");
file.close();
}
}
}
UI界面如下:
下面贴服务器端的 代码
1.也是先添加network
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QTcpServer>
#include<QTcpSocket>
#include<QFile>
#include <QHostAddress>
#include<QDebug>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void connectedSlot();
void recvSlot();
private:
Ui::Widget *ui;
QTcpServer *server;
QTcpSocket *socket;
QString fileName;
int fileSize;
bool flag;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("接收端");
server = new QTcpServer(this);
//服务器一打开就进行监听查询,
server->listen(QHostAddress("192.168.0.111"),8888);
flag = true;
connect(server,SIGNAL(newConnection()),this,SLOT(connectedSlot()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::connectedSlot()
{
socket = server->nextPendingConnection();
if(NULL == socket)
{
return ;
}
connect(socket,SIGNAL(readyRead()),this,SLOT(recvSlot()));
}
void Widget::recvSlot()
{
QByteArray arr = socket->readAll();
if(true == flag)
{
qDebug()<<QString(arr);
QString str = QString(arr);
fileName = str.section("##",0,0);
fileSize = str.section("##",1,1).toInt();
ui->textBrowser->setText("要接收的文件信息为:"+fileName+QString::number(fileSize));
flag = false;
}
else
{
//这是后面上传文件以后需要存储的绝对路径
QFile file("F:\\"+fileName);
bool ok = file.open(QIODevice::WriteOnly);
qint64 size = 0;
if(true == ok)
{
qint64 ret = file.write(arr);
size += ret ;
if(size ==fileSize)
{
ui->textBrowser->append("文件接受完成!");
flag = true;
file.close();
}
}
}
}
ui 界面如下