总结:
1.QFile file(name)
file.setFileName()
readAll()/readLine()----atEnd()==true,文件到结尾了
int size = write(char* buf, int size);
2.QTextStream ts(&f);
ts.setDevice(&f);
readAll()/ readLine()
ts << "abcdef"; // 将内容abcdeef,写入到ts中。
ts >> str; // 从设备中取内容,放到str中。
3.QDataStream ds(&f);
读文件:
ds >> str >> number;
写文件:
ds << str << number; // 读写的顺序,要保持一致。
4.QByteArray array;
QPixmap pix;
QDataStream ds(&array, QIODevice::WriteOnly);
ds << pix;
5.TCP,依赖模块是 qmake += network。
【服务器端】:
a.listen:QTcpServer-- 不是IO设备。父类是QObject。
b.通信:QTcpSocket--IO设备,父类是QIODevice *conn
- 服务器端监听,server.listen(Any, port);
- newConnection(); 接收请求,拿到client端的套接字对象的地址。
conn = server.nextPendingConnection();
- write()
- read()读数据,readyRead信号,表示数据来了。
【客户端】:QTcpSocket cl;
a. cl.connectToHost(IP, port); // 都是服务器的ip和port
// 获取客户端基本信息
QTcpSocket *ss;
ss = server.nextPendingConnection();
sockList.append(ss);
QString IP = ss->peerAddress().toString();
quint16 port = ss->peerPort();
QList<QTcpSocket*> sockList; // tcp连接多个
6.UDP类:QUdpSocket--- io设备。
- 发数据:s.writeDatagrame(data, 对方IP,对方Port)
- readyRead()信号 去读数据
quint64 size = s.pendingDatagrameSize();
QByteArray array(size, 0); // 不要delete
s.readDatagrame(array.data(), size); - udp接收数据:要绑定端口号(本地的)
- 广播地址:255.255.255.255
- 组播地址:好几个组播地址。 加入到组播地址joinMulticastGroup().
文件传输。
传输的时候,文件的大小和文件名先传输过去。
熊出没.avi##10000
当接收的字节数 == 文件的大小,代表文件接收完成了。
组装的头先发送,然后分块读取文件。
每收到一条数据,就往文件中写一条数据。
QString str;
str.section("##", 0,0) == 熊出没.avi
section("##", 0,1) == 熊出没 10000
1.服务器端
serverwidget.h
#ifndef SERVERWIDGET_H
#define SERVERWIDGET_H
#include <QMainWindow>
#include <QTcpServer> //network
#include <QTcpSocket>
#include <QFile>
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class ServerWidget; }
QT_END_NAMESPACE
class ServerWidget : public QMainWindow
{
Q_OBJECT
public:
ServerWidget(QWidget *parent = nullptr);
~ServerWidget();
private:
void on_buttonChoose_clicked();
void on_buttonSend_clicked();
void sendFileData();
Ui::ServerWidget *ui;
QTcpServer* tcpServer; //监听的套接字
QTcpSocket* tcpSocket; //通信的套接字
QTimer timer ; //定时器
QString fileName = "";
qint64 fileSize =0;
qint64 sendSize =0;
QFile file;
};
#endif // SERVERWIDGET_H
//https://www.cnblogs.com/lalala-lueluelue/p/12673764.html
serverwidget.cpp
#include "serverwidget.h"
#include "ui_serverwidget.h"
#include <QMessageBox>
#include <QTimer>
#include <QFileDialog>
ServerWidget::ServerWidget(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::ServerWidget)
{
ui->setupUi(this);
tcpServer = new QTcpServer(this);
bool isOk = tcpServer->listen(QHostAddress::Any, 8888);
if(!isOk){ // listen failed
QMessageBox::warning(this, "监听", "监听失败");
return;
}
setWindowTitle("服务器:8888");
ui->buttonChoose->setEnabled(false);
ui->buttonSend->setEnabled(false);
//当有客户端连接时,触发信号newConnection
connect(tcpServer, &QTcpServer::newConnection, [=](){
//
tcpSocket = tcpServer->nextPendingConnection();
QString ip = tcpSocket->peerAddress().toString();
qint16 port = tcpSocket->peerPort();
QString str = QString("[1%: 2%]和服务器连接成功").arg(ip).arg(port);
ui->textEdit->setText(str);
ui->buttonChoose->setEnabled(true);
QMessageBox::information(this, "允许", "连接成功,可以选择文件发送。");
});
connect(&timer, &QTimer::timeout, [=](){
this->timer.stop();
sendFileData(); // send file data
});
}
ServerWidget::~ServerWidget()
{
delete ui;
}
// select file btn
void ServerWidget::on_buttonChoose_clicked()
{
QString path = QFileDialog::getOpenFileName(this,"请选择所要发送的文件", "../");
if(path.isEmpty() == false) { // 路径有效
file.setFileName(path);
bool isOk = file.open(QIODevice::ReadOnly);
if(false==isOk) {
QMessageBox::warning(this, "Warning", "Open file failed");
return;
}else {
ui->textEdit->append("to send File:");
ui->textEdit->append(path);
// init data
fileName = "";
fileSize =0;
sendSize =0;
// 获取发送文件的信息
QFileInfo info(path);
fileName = info.fileName();
fileSize = info.size();
ui->buttonSend->setEnabled(true);
ui->buttonChoose->setEnabled(false);
}
}
}
void ServerWidget::on_buttonSend_clicked()
{
ui->buttonSend->setEnabled(false);
QString buf = QString("head#%1#%2").arg(fileName).arg(fileSize);
qint64 len = tcpSocket->write(buf.toUtf8().data());
tcpSocket->waitForBytesWritten();//等待数据发送完毕
ui->textEdit->append("已经在发送文件!!");
if(len>0) {
this->timer.start(1000);
//delay avoid package rebuild.
}else {
file.close();
}
}
void ServerWidget::sendFileData()
{
qint64 len =0;
do{
char buf[2048] = {0};
len = 0;
len = file.read(buf, sizeof(buf)); // read data
len = tcpSocket->write(buf,len); // send data
sendSize += len;
}while(len >0);
if(sendSize == fileSize)
{
ui->textEdit->append("文件发送完毕 ");
file.close();
tcpSocket->disconnectFromHost();
tcpSocket->close();
}
}
2.client端
clientwidget.h
#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H
#include <QWidget>
#include <QtNetwork> //network
#include <QFile>
namespace Ui {
class ClientWidget;
}
class ClientWidget : public QWidget
{
Q_OBJECT
public:
explicit ClientWidget(QWidget *parent = nullptr);
~ClientWidget();
private slots:
void on_ButtonConnect_clicked();
private:
Ui::ClientWidget *ui;
QTcpSocket* tcpSocket;//通信套接字
QFile file;//文件对象
QString fileName = "";//文件名称,大小
qint64 fileSize =0;//
qint64 recvSize =0; //已接收文件的大小
bool isFile;//接收文件数据标志
};
#endif // CLIENTWIDGET_H
clientwidget.cpp
#include "clientwidget.h"
#include "ui_clientwidget.h"
#include <QDebug>
#include <QMessageBox>
ClientWidget::ClientWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::ClientWidget)
{
ui->setupUi(this);
//set tcp socket
tcpSocket = new QTcpSocket(this);
setWindowTitle("客户端");
connect(tcpSocket, &QTcpSocket::connected, this, [=](){
// init data
fileName = "";
fileSize =0;
recvSize =0;
isFile = false;
ui->buttonConnect->setEnabled(false);
ui->textEdit->clear();
ui->textEdit->append("与服务器连接成功。");
});
ui->progressBar->setValue(0);
// when have data to receive
connect(tcpSocket, &QTcpSocket::readyRead, [=](){
QByteArray buf = tcpSocket->readAll(); //全部读取进来
if(false == isFile) { // 先接收头部信息 head
isFile = true;
//"head#fileName#fileSize" 截取字符串
fileName = QString(buf).section("#", 1,1);
fileSize = QString(buf).section("#", 2,2).toInt();
qDebug() << fileName << fileSize;
recvSize =0;
file.setFileName(fileName);
if(false == file.open(QIODevice::WriteOnly)){
//init data
fileName = "";
fileSize =0;
recvSize =0;
isFile = false;
QMessageBox::warning(this,"警告", "创建文件失败");
return;
}
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(fileSize/1024);
ui->textEdit->append("正在接收文件:\n");
ui->textEdit->append(fileName);
} else {
// 文件数据,最重要的一部分
qint64 len = file.write(buf);
recvSize += len;
qDebug() << len;
ui->progressBar->setMaximum(recvSize/1024);
}
//文件接收完毕
if(recvSize == fileSize) {
file.close();
ui->buttonConnect->setEnabled(true);
tcpSocket->disconnectFromHost();
QMessageBox::information(this,"ok", "File receive finished.");
ui->textEdit->append("文件接收完毕");
}
});
}
ClientWidget::~ClientWidget()
{
delete ui;
}
//连接按钮
void ClientWidget::on_ButtonConnect_clicked()
{
ui->progressBar->setValue(0);
QString ip = ui->lineEditIP->text();
quint16 port = ui->lineEditPort->text().toInt();
if(ip.isEmpty() || port==0) {
QMessageBox::information(this,"警告", "ip/port can't be null.");
return ;
}
tcpSocket->abort(); //取消已有的连接
tcpSocket->connectToHost(QHostAddress(ip), port); //连接服务器
}
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 cw;
cw.show();
return a.exec();
}







网友评论