一个 文件传说 的东西...
先看 发送 的..
头文件
header.h
- #ifndefHEADER_H
- #defineHEADER_H
- #include<QDialog>
- #include<QTcpSocket>
- #include<QAbstractSocket>
- class QTcpSocket;
- class QDialogButtonBox;
- class QDialog;
- class QFile;
- class QProgressBar;
- class QLabel;
- class QVBoxLayout;
- class QTimer;
- class Dialog: public QDialog{
- Q_OBJECT
- public :
- Dialog(QWidget*parent=0);
- public slots:
- void start();
- void quit();
- void startTransfer();
- void updateClientProgress(qint64numBytes);
- void displayError(QAbstractSocket::SocketErrorsocketError);
- void openFile();
- void connectError();
- private :
- QProgressBar*clientProgressBar;
- QLabel*clientStatusLabel;
- QPushButton*startButton;
- QPushButton*quitButton;
- QPushButton*openButton;
- QDialogButtonBox*buttonBox;
- QVBoxLayout*mainLayout;
- QTcpSockettcpClient;
- int flag;
- qint64TotalBytes;
- qint64bytesWritten;
- qint64bytesToWrite;
- qint64localSize;
- QTimer*timer;
- QStringfileName;
- QFile*localFile;
- QByteArrayoutBlock;
- };
- #endif//HEADER_H
#ifndef HEADER_H #define HEADER_H #include <QDialog> #include <QTcpSocket> #include <QAbstractSocket> class QTcpSocket; class QDialogButtonBox; class QDialog; class QFile; class QProgressBar; class QLabel; class QVBoxLayout; class QTimer; class Dialog:public QDialog{ Q_OBJECT public: Dialog(QWidget *parent=0); public slots: void start(); void quit(); void startTransfer(); void updateClientProgress(qint64 numBytes); void displayError(QAbstractSocket::SocketError socketError); void openFile(); void connectError(); private : QProgressBar *clientProgressBar; QLabel *clientStatusLabel; QPushButton *startButton; QPushButton *quitButton; QPushButton *openButton; QDialogButtonBox *buttonBox; QVBoxLayout *mainLayout; QTcpSocket tcpClient; int flag; qint64 TotalBytes; qint64 bytesWritten; qint64 bytesToWrite; qint64 localSize; QTimer *timer; QString fileName; QFile *localFile; QByteArray outBlock; }; #endif // HEADER_H
main.cpp
- #include<QtGui>
- #include<QHostAddress>
- #include"header.h"
- //构造函数一些初始化操作
- Dialog::Dialog(QWidget*parent):QDialog(parent){
- localSize=4*1024;
- TotalBytes=0;
- bytesWritten=0;
- bytesToWrite=0;
- setWindowTitle(tr("发送文件" ));
- clientProgressBar=new QProgressBar;
- clientStatusLabel=new QLabel(tr( "客户端准备完毕" ));
- startButton=new QPushButton(tr( "开始" ));
- quitButton=new QPushButton(tr( "退出" ));
- openButton=new QPushButton(tr( "打开" ));
- startButton->setEnabled(false );
- buttonBox=new QDialogButtonBox;
- buttonBox->addButton(startButton,QDialogButtonBox::ActionRole);
- buttonBox->addButton(openButton,QDialogButtonBox::ActionRole);
- buttonBox->addButton(quitButton,QDialogButtonBox::RejectRole);
- mainLayout=new QVBoxLayout;
- mainLayout->addWidget(clientProgressBar);
- mainLayout->addWidget(clientStatusLabel);
- mainLayout->addWidget(buttonBox);
- setLayout(mainLayout);
- connect(startButton,SIGNAL(clicked()),this ,SLOT(start()));
- connect(openButton,SIGNAL(clicked()),this ,SLOT(openFile()));
- connect(quitButton,SIGNAL(clicked()),this ,SLOT(quit()));
- timer=new QTimer( this );
- //connect(timer,SIGNAL(timeout()),this,SLOT(connectError()));
- connect(&tcpClient,SIGNAL(connected()),this ,SLOT(startTransfer()));
- connect(&tcpClient,SIGNAL(bytesWritten(qint64)),this ,SLOT(updateClientProgress(qint64)));
- connect(&tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this ,SLOT(displayError(QAbstractSocket::SocketError)));
- flag=1;
- }
- //连接超时错误
- void Dialog::connectError(){
- }
- //退出
- void Dialog::quit(){
- qApp->quit();
- }
- //开始连接服务器
- void Dialog::start(){
- timer->start(1000);
- startButton->setEnabled(false );
- QApplication::setOverrideCursor(Qt::WaitCursor);
- bytesWritten=0;
- clientStatusLabel->setText(tr("连接中" ));
- tcpClient.connectToHost(QHostAddress::LocalHost,8888);
- }
- //打开文件
- void Dialog::openFile(){
- fileName=QFileDialog::getOpenFileName(this );
- if (!fileName.isEmpty()){
- startButton->setEnabled(true );
- }
- }
- void Dialog::startTransfer(){
- //只读方式打开文件
- localFile=new QFile(fileName);
- if (!localFile->open(QFile::ReadOnly)){
- QMessageBox::warning(this ,tr( "应用程序" ),tr( "无法读取文件" ).arg(fileName).arg(localFile->errorString()));
- return ;
- }
- //获取文件大小
- TotalBytes=localFile->size();
- //发送缓冲区outBlock封装在一个QDataStream类型变量中
- QDataStreamsendOut(&outBlock,QIODevice::WriteOnly);
- //设置流化数据版本
- sendOut.setVersion(QDataStream::Qt_4_6);
- //通过.right去掉文件的路径部分,
- //fileName.lastIndexOf('/')返回的是文件最后一个/所在的位数(INT)
- //fileName.right()返回的是从右面开始数的位数的值.
- //例如路径如果是D:\MyDocuments\Tcp\header.h
- //fileName.lastIndexOf('/')返回的是从D开始到最后一个\的位数
- //fileName.right(8)意思就是从路径右面开始到第八位数的字符串
- QStringcurrentFile=fileName.right(fileName.size()-fileName.lastIndexOf('/' )-1);
- //构造一个临时文件头将总长度和文件名长度暂时为0
- sendOut<<qint64(0)<<qint64(0)<<currentFile;
- //获得文件头的实际存储大小追加到TotalBytes;
- TotalBytes+=outBlock.size();
- //将读写操作指向文件头.
- sendOut.device()->seek(0);
- //填写实际总长度和文件长度
- sendOut<<TotalBytes<<qint64((outBlock.size()-sizeof (qint64)*2));
- //调用write函数将文件头发出同时修改bytesToWrite;
- bytesToWrite=TotalBytes-tcpClient.write(outBlock);
- clientStatusLabel->setText(tr("已经连接" ));
- qDebug()<<currentFile<<TotalBytes;
- //清空缓冲区
- outBlock.resize(0);
- }
- //数据发出将会产生bytesWritten()信号然后调用此方法参数表示实际已发出的字节
- void Dialog::updateClientProgress(qint64numBytes){
- bytesWritten+=(int )numBytes;
- if (bytesToWrite>0){
- outBlock=localFile->read(qMin(bytesToWrite,localSize));
- bytesToWrite-=(int )tcpClient.write(outBlock);
- outBlock.resize(0);
- }else {
- localFile->close();
- }
- clientProgressBar->setMaximum(TotalBytes);
- clientProgressBar->setValue(bytesWritten);
- clientStatusLabel->setText(tr("已发送%1M" ).arg(bytesWritten/(1024*1024)));
- }
- //链接错误方法
- void Dialog::displayError(QAbstractSocket::SocketErrorsocketError){
- if (socketError=QTcpSocket::RemoteHostClosedError)
- return ;
- QMessageBox::information(this ,tr( "网络" ),tr( "产生如下错误:%1." ).arg(tcpClient.errorString()));
- tcpClient.close();
- clientProgressBar->reset();
- clientStatusLabel->setText(tr("客户端就绪" ));
- startButton->setEnabled(true );
- QApplication::restoreOverrideCursor();
- }
- int main( int argc, char **argv){
- QApplicationapp(argc,argv);
- QTextCodec::setCodecForTr(QTextCodec::codecForName("gb2312" ));
- Dialogdialog;
- dialog.show();
- return app.exec();
- }
#include <QtGui> #include <QHostAddress> #include "header.h" //构造函数 一些初始化操作 Dialog::Dialog(QWidget *parent):QDialog(parent){ localSize=4*1024; TotalBytes=0; bytesWritten=0; bytesToWrite=0; setWindowTitle(tr("发送文件")); clientProgressBar=new QProgressBar; clientStatusLabel=new QLabel(tr("客户端准备完毕")); startButton=new QPushButton(tr("开始")); quitButton=new QPushButton(tr("退出")); openButton=new QPushButton(tr("打开")); startButton->setEnabled(false); buttonBox=new QDialogButtonBox; buttonBox->addButton(startButton,QDialogButtonBox::ActionRole); buttonBox->addButton(openButton,QDialogButtonBox::ActionRole); buttonBox->addButton(quitButton,QDialogButtonBox::RejectRole); mainLayout=new QVBoxLayout; mainLayout->addWidget(clientProgressBar); mainLayout->addWidget(clientStatusLabel); mainLayout->addWidget(buttonBox); setLayout(mainLayout); connect(startButton,SIGNAL(clicked()),this,SLOT(start())); connect(openButton,SIGNAL(clicked()),this,SLOT(openFile())); connect(quitButton,SIGNAL(clicked()),this,SLOT(quit())); timer=new QTimer(this); // connect(timer,SIGNAL(timeout()),this,SLOT(connectError())); connect(&tcpClient,SIGNAL(connected()),this,SLOT(startTransfer())); connect(&tcpClient,SIGNAL(bytesWritten(qint64)),this,SLOT(updateClientProgress(qint64))); connect(&tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError))); flag=1; } //连接超时错误 void Dialog::connectError(){ } //退出 void Dialog::quit(){ qApp->quit(); } //开始连接服务器 void Dialog::start(){ timer->start(1000); startButton->setEnabled(false); QApplication::setOverrideCursor(Qt::WaitCursor); bytesWritten=0; clientStatusLabel->setText(tr("连接中")); tcpClient.connectToHost(QHostAddress::LocalHost,8888); } //打开文件 void Dialog::openFile(){ fileName=QFileDialog::getOpenFileName(this); if(!fileName.isEmpty()){ startButton->setEnabled(true); } } void Dialog::startTransfer(){ //只读方式打开文件 localFile=new QFile(fileName); if(!localFile->open(QFile::ReadOnly)){ QMessageBox::warning(this,tr("应用程序"),tr("无法读取文件").arg(fileName).arg(localFile->errorString())); return ; } //获取 文件大小 TotalBytes=localFile->size(); //发送缓冲区outBlock封装在一个QDataStream类型变量中 QDataStream sendOut(&outBlock,QIODevice::WriteOnly); //设置流化数据版本 sendOut.setVersion(QDataStream::Qt_4_6); //通过.right去掉 文件的路径部分, //fileName.lastIndexOf('/')返回的是 文件最后一个 / 所在的位数(INT) //fileName.right()返回的是 从右面开始数 的位数的值. //例如 路径如果是D:\My Documents\Tcp\header.h //fileName.lastIndexOf('/')返回的是从D开始 到最后一个 \ 的位数 //fileName.right(8) 意思就是 从路径右面开始 到第八位数的字符串 QString currentFile=fileName.right(fileName.size()-fileName.lastIndexOf('/')-1); //构造一个临时文件头 将总长度和文件名长度暂时为0 sendOut<<qint64(0)<<qint64(0)<<currentFile; //获得文件头的实际存储大小 追加到 TotalBytes; TotalBytes+=outBlock.size(); //将读写操作指向文件头. sendOut.device()->seek(0); //填写实际总长度和文件长度 sendOut<<TotalBytes<<qint64((outBlock.size()-sizeof(qint64)*2)); //调用 write函数将文件头发出同时修改 bytesToWrite; bytesToWrite=TotalBytes-tcpClient.write(outBlock); clientStatusLabel->setText(tr("已经连接")); qDebug()<<currentFile<<TotalBytes; //清空缓冲区 outBlock.resize(0); } //数据发出 将会产生 bytesWritten()信号 然后调用此方法 参数表示实际已发出的字节 void Dialog::updateClientProgress(qint64 numBytes){ bytesWritten+=(int)numBytes; if(bytesToWrite>0){ outBlock=localFile->read(qMin(bytesToWrite,localSize)); bytesToWrite-=(int)tcpClient.write(outBlock); outBlock.resize(0); }else{ localFile->close(); } clientProgressBar->setMaximum(TotalBytes); clientProgressBar->setValue(bytesWritten); clientStatusLabel->setText(tr("已发送 %1 M").arg(bytesWritten/(1024*1024))); } //链接错误方法 void Dialog::displayError(QAbstractSocket::SocketError socketError){ if(socketError=QTcpSocket::RemoteHostClosedError) return; QMessageBox::information(this,tr("网络"),tr("产生如下错误: %1.").arg(tcpClient.errorString())); tcpClient.close(); clientProgressBar->reset(); clientStatusLabel->setText(tr("客户端就绪")); startButton->setEnabled(true); QApplication::restoreOverrideCursor(); } int main(int argc,char **argv){ QApplication app(argc,argv); QTextCodec::setCodecForTr( QTextCodec::codecForName("gb2312")); Dialog dialog; dialog.show(); return app.exec(); }
再看 接受文件
header.h
- #ifndefDIALOG_H
- #defineDIALOG_H
- #include<QDialog>
- #include<QTcpServer>
- class QFile;
- class QDialogButtonBox;
- class QLabel;
- class QProgressBar;
- class QPushButton;
- class QTcpSocket;
- class Dialog: public QDialog
- {
- Q_OBJECT
- public :
- Dialog(QWidget*parent=0);
- public slots:
- void start();
- void acceptConnection();
- void updateServerProgress();
- void displayError(QAbstractSocket::SocketErrorsocketError);
- private :
- QProgressBar*clientProgressBar;
- QProgressBar*serverProgressBar;
- QLabel*serverStatusLabel;
- QPushButton*startButton;
- QPushButton*quitButton;
- QPushButton*openButton;
- QDialogButtonBox*buttonBox;
- QTcpServertcpServer;
- QTcpSocket*tcpServerConnection;
- qint64TotalBytes;
- qint64bytesReceived;
- qint64fileNameSize;
- QStringfileName;
- QFile*localFile;
- QByteArrayinBlock;
- };
- #endif
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QTcpServer> class QFile; class QDialogButtonBox; class QLabel; class QProgressBar; class QPushButton; class QTcpSocket; class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); public slots: void start(); void acceptConnection(); void updateServerProgress(); void displayError(QAbstractSocket::SocketError socketError); private: QProgressBar *clientProgressBar; QProgressBar *serverProgressBar; QLabel *serverStatusLabel; QPushButton *startButton; QPushButton *quitButton; QPushButton *openButton; QDialogButtonBox *buttonBox; QTcpServer tcpServer; QTcpSocket *tcpServerConnection; qint64 TotalBytes; qint64 bytesReceived; qint64 fileNameSize; QString fileName; QFile *localFile; QByteArray inBlock; }; #endif
再看 实现文件
dialog.cpp
- #include"receiver.h"
- #include<QtNetwork>
- Receiver::Receiver(QObject*parent)
- :QObject(parent)
- {
- udpSocket=new QUdpSocket( this );
- udpSocket->bind(44444);
- connect(udpSocket,SIGNAL(readyRead()),
- this ,SLOT(processPendingDatagrams()));
- }
- void Receiver::processPendingDatagrams()
- {
- while (udpSocket->hasPendingDatagrams()){
- QByteArraydatagram;
- datagram.resize(udpSocket->pendingDatagramSize());
- udpSocket->readDatagram(datagram.data(),datagram.size());
- qDebug()<<(tr("接收数据:\"%1\"" )
- .arg(datagram.data()));
- }
- }
#include "receiver.h" #include <QtNetwork> Receiver::Receiver(QObject *parent) : QObject(parent) { udpSocket = new QUdpSocket(this); udpSocket->bind(44444); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); } void Receiver::processPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); qDebug()<<(tr("接收数据: \"%1\"") .arg(datagram.data())); } }
然后是 main.cpp
- #include<QApplication>
- #include<QtCore>
- #include"dialog.h"
- int main( int argc, char *argv[])
- {
- QApplicationapp(argc,argv);
- QTextCodec::setCodecForTr(QTextCodec::codecForName("gb2312" ));
- Dialogdialog;
- dialog.show();
- return dialog.exec();
- }
#include <QApplication> #include <QtCore> #include "dialog.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); QTextCodec::setCodecForTr( QTextCodec::codecForName("gb2312")); Dialog dialog; dialog.show(); return dialog.exec(); }
执行结果如下..