tcp文件传输(udp发送消息确定是否接收)

来源:互联网 发布:计算型材米重的软件 编辑:程序博客网 时间:2024/05/19 01:10

原文链接  http://blog.bccn.net/liYX9553/61129


dialog.h:

#ifndef DIALOG_H#define DIALOG_H #include <QDialog>#include <QTime> class QTcpServer;class QFile;class QTcpSocket;class QUdpSocket; namespace Ui {class Dialog;} class Dialog : public QDialog{    Q_OBJECT public:    explicit Dialog(QWidget *parent = 0);    ~Dialog();    void initser();// 初始化服务器。  private:    Ui::Dialog *ui;    qint16 tport;    qint16 uport;    qint16 u2port;    qint64 totalBytes;    qint64 writeBytes;    qint64 tobeWriteBytes;    qint64 payloadSize;//被初始化为第一个常量。    QByteArray outBlock;     QTcpSocket *clintcon;    QUdpSocket *udpSocket;    QTcpServer *tser;    QString fileName;    QString theFileName;     QFile *locFile;    QTime time;protected:    void SendFileName(QString fileName);    QString getIP();private slots:    void sendMsg();    void updClintProgress(qint64 numBytes);    void getFileName(QString name);    void refused();//关闭服务器。    void on_sCloseBtn_clicked();     void on_sOpenBtn_clicked();     void on_sSendBtn_clicked(); signals:    void sendFileName(QString fileName);}; #endif // DIALOG_H


dialog.cpp:

#include "dialog.h"#include "ui_dialog.h"#include <QFile>#include <QDebug>#include <QMessageBox>#include <QFileDialog>#include <QTcpServer>#include <QTcpSocket>#include <QNetworkInterface>#include "QObject"#include <QUdpSocket>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include <qtcpserver.h> Dialog::Dialog(QWidget *parent) :    QDialog(parent),    ui(new Ui::Dialog){    ui->setupUi(this);    udpSocket = new QUdpSocket(this);    uport = 8888;    u2port = 7777;    udpSocket->bind(u2port, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(refused()));    //sendMessage(NewParticipant);    tport = 6666;    tser = new QTcpServer(this);    connect(tser,SIGNAL(newConnection()),this,SLOT(sendMsg()));    connect(this,SIGNAL(sendFileName(QString)),this,SLOT(getFileName(QString)));    initser();} Dialog::~Dialog(){    delete ui;}void Dialog::initser()//初始化服务器。{    totalBytes = 0;    tobeWriteBytes = 0;    writeBytes = 0;    ui->sOpenBtn->setEnabled(true);//open按钮可用    ui->sSendBtn->setEnabled(false);//发送按钮不可用     ui->label_2->setText("请选择要发送的文件");    tser->close();}void Dialog::refused()//关闭服务器。{    tser->close();    ui->label_2->setText(tr("对方拒绝接收!"));}//发送文件void Dialog::sendMsg(){    qDebug() << "--------sendMsg start-----------" ;    ui->sSendBtn->setEnabled(false);//设置按钮不可用    clintcon = tser->nextPendingConnection();//获取一个已经连接tcp套接字。    connect(clintcon,SIGNAL(bytesWritten(qint64)),this,SLOT(updClintProgress(qint64)));     ui->label_2->setText(tr("开始传送文件 %1!").arg(theFileName));    locFile = new QFile(fileName);//只读方式打开文档    if(!locFile->open((QFile::ReadOnly))){         QMessageBox::warning(this,tr(""),tr("无法读取文件%1:\n %2").arg(fileName).arg(locFile->errorString()));         return;    }    totalBytes = locFile->size();//文件的总字节数。    qDebug() << "fileTotalBytes:" << totalBytes;    QDataStream sendOut(&outBlock,QIODevice::WriteOnly);    sendOut.setVersion(QDataStream::Qt_4_7);    time.start();    QString curFile = fileName.right(fileName.size() - fileName.lastIndexOf('/') -1 );//待发送文件名。    qDebug() << "curFile:" << curFile;    sendOut << qint64(0) << qint64(0) << curFile;    totalBytes += outBlock.size();//文件名大小信息+实际文件大小。    sendOut.device()->seek(0);//设置文件指针从0开始    sendOut << totalBytes <<  qint64((outBlock.size() - sizeof(qint64)*2));    tobeWriteBytes = totalBytes - clintcon->write(outBlock);//发送缓存区的数据,同时修改待发送的数据长度。    qDebug() << "tobeWriteBytes:" << tobeWriteBytes;    qDebug() << "outBlock:" << outBlock;    outBlock.resize(0);} void Dialog::on_sCloseBtn_clicked(){    if(tser->isListening()){        tser->close();//当tcp正在监听时,关闭tcp服务器端应用,即按下close键时就不监听tcp请求了        if(locFile->isOpen()){            locFile->close();        }        clintcon->abort();//Socket::终止当前的连接,禁止写入缓存区。    }    close();} void Dialog::on_sOpenBtn_clicked(){    fileName = QFileDialog::getOpenFileName(this, tr("Open File"),                 "/home"                 );//tr("Images (*.png *.xpm *.jpg *.txt *.gz)")    //fileName = QFileDialog::getOpenFileName(this);    if(theFileName.isEmpty()){        theFileName = fileName.right(fileName.size() - fileName.lastIndexOf('/') - 1);        ui->label_2->setText(tr("要发送的文件为:%1").arg(theFileName));        qDebug() << "thefilename:" << theFileName;    }    qDebug() << "fileName:" << fileName;    ui->sSendBtn->setEnabled(true);} void Dialog::on_sSendBtn_clicked(){        qint8 a;        a = tser->listen(QHostAddress::Any,tport);    if(!a){        qDebug() << tser->errorString();        close();    }    qDebug() << a;    ui->label_2->setText(tr("等待对方接收...."));    emit sendFileName(theFileName);    qDebug() << "-----emit- success!------";    ui->sSendBtn->setEnabled(false);}//进度条修改进度。void Dialog::updClintProgress(qint64 numBytes){    qDebug() << "udpClintProgress  start....";    qApp->processEvents();    //qDebug() << "writeBytes1:"<< writeBytes;    //writeBytes += (int)numBytes;    //qDebug() << "writeBytes2:" << writeBytes;    if(tobeWriteBytes > 0){//没发送完。        outBlock = locFile->read(qMin(tobeWriteBytes,payloadSize));//每次最多发送64k大小。        tobeWriteBytes -= (int)clintcon->write(outBlock);        writeBytes += (totalBytes - tobeWriteBytes);//已经发送了的。        outBlock.resize(0);    }else {        locFile->close();    }    ui->progressBar->setMaximum(totalBytes);    ui->progressBar->setValue(writeBytes);    float useTime = time.elapsed();    double speed = writeBytes/useTime*1000000;     ui->label_2->setText(tr("(%1 m/s)").arg(speed));    qDebug() << "writeBytes:"<< writeBytes;    qDebug() << "totalBytes:" << totalBytes;     if(writeBytes == totalBytes){        locFile->close();        tser->close();        ui->label_2->setText(tr("文件:%1发送成功!").arg(theFileName));    } }//获取文件名void Dialog::getFileName(QString name){        qDebug() << "------1getFileName--------" << name;        theFileName = name;        //qDebug() << "fileNamesize" << strlen(fileName);        SendFileName(theFileName);}//发送文件名void Dialog::SendFileName(QString fileName){        QByteArray data;        QDataStream out(&data, QIODevice::WriteOnly);         QString address,clientaddr;        address  = getIP();        //clientaddr = getIP();        //QString clientAddress = ui->userTableWidget->item(row, 2)->text();//(row,,2)为ip地址        out << address << fileName;//发送本地ip,所发送的文件名        qDebug() << "SendFileName :" << fileName;        qDebug() << "server IP:" << address;        int a= udpSocket->writeDatagram(data,data.length(),QHostAddress::Broadcast, uport);//向8888端口广播        qDebug() << "a" << a;}//获取IPQString Dialog::getIP(){    QList<QHostAddress> list = QNetworkInterface::allAddresses();    foreach (QHostAddress address, list) {        if(address.protocol() == QAbstractSocket::IPv4Protocol){            if(address.toString().contains("192.168.1")||address.toString().contains("127.0"))                continue;            return address.toString();        }    }    return 0;}

client.h

#ifndef DIALOG_H#define DIALOG_H #include <QDialog>#include <QHostAddress>#include <QFile>#include <QTime>#include <QDebug>#include <QMessageBox>#include"thread.h"enum MessageType{FileName, refuse};class QTcpSocket;class QUdpSocket;namespace Ui {class Dialog;} class Dialog : public QDialog{    Q_OBJECT public:    explicit Dialog(QWidget *parent = 0);    ~Dialog();     void setHostaddr(QHostAddress addr);                         //获取主机ip    void setFileName(QString FileName);                         //获取文件保存路径    void reciveFileNmae();private slots:     void on_cCancelBtn_clicked();     void on_cClosebtn_clicked(); protected:    void SendRefuse(MessageType type);    void closeEvent(QCloseEvent *);    void hansPendingFile(QString serAddress,QString fileName);    QString getIP();private:    Thread *b;    Ui::Dialog *ui;    QUdpSocket *udpSocket;    QTcpSocket *cClint;     QHostAddress hostAddr;    qint16 tport;    qint16 uport;    qint16 u2port;    quint16 blockSize;    qint64 totalBytes;    qint64 recevBytes;    qint64 fileNameSize;     QString FileName;    QString *SerAdress;    QFile *locFile;                          //要接收的文件     QByteArray inBlock;                     //缓存一次接收的数据    QTime Time;private slots:    void processPendingDatarams();    void newConn();    void readMsg();    void displayError(QAbstractSocket::SocketError); signals: }; #endif // DIALOG_H


client.cpp

#include "dialog.h"#include "ui_dialog.h" #include <QTcpSocket>#include <QUdpSocket>#include <QTime>#include <QDebug>#include <QMessageBox>#include <QNetworkInterface>#include <QFile>#include <QFileDialog>#include <QDateTime>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <qiodevice.h>  Dialog::Dialog(QWidget *parent) :    QDialog(parent),    ui(new Ui::Dialog){    ui->setupUi(this);    setWindowTitle("client");    totalBytes = 0;    recevBytes = 0;    fileNameSize = 0;    udpSocket = new QUdpSocket(this);    uport = 8888;    u2port = 7777;    udpSocket->bind(QHostAddress::Broadcast, uport, QUdpSocket::ShareAddress| QUdpSocket::ReuseAddressHint);    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatarams()));    tport = 6666;    cClint = new QTcpSocket(this);    connect(cClint,SIGNAL(readyRead()),this,SLOT(readMsg()));    connect(cClint, SIGNAL(error(QAbstractSocket::SocketError)), this,                SLOT(displayError(QAbstractSocket::SocketError)));}Dialog::~Dialog(){    delete ui;}// 设置地址void Dialog::setHostaddr(QHostAddress addr){    qDebug() << "--------setHostaddr---------";    hostAddr = addr;    qDebug() << "hostAddr:" << hostAddr;    newConn();}//设置文件名void Dialog::setFileName(QString FileName){    locFile = new QFile(FileName);}void Dialog::newConn()                   // 设置与服务器建立连接的。{    qDebug() << "---------newConn start---------";    blockSize = 0;    cClint->abort();    cClint->connectToHost(hostAddr,tport);    Time.start();}//接收文件void Dialog::readMsg(){    qDebug() << "-----------readMsg start-----------";    QDataStream in(cClint);    in.setVersion(QDataStream::Qt_4_7);     float useTime = Time.elapsed();    if(recevBytes <= sizeof(qint64)*2){        if((cClint->bytesAvailable() >= sizeof(qint64)*2)&& fileNameSize == 0){            //接收数据总大小信息和数据文件名大小。            in >> totalBytes >> fileNameSize;            qDebug() << "totalBytes:" << totalBytes;            qDebug() << "fileNameSize:" << fileNameSize;            recevBytes += sizeof(qint64)*2;            qDebug() << "1recevBytes:" << recevBytes;        }        if((cClint->bytesAvailable() >= fileNameSize) && (fileNameSize != 0)){            //开始接收文件,并建立文件。            in >> FileName;            qDebug() << "FileName:" << FileName;            recevBytes += fileNameSize;            qDebug() << "2recevBytes:" << recevBytes;            if(!locFile->open(QFile::WriteOnly)){                QMessageBox::warning(this,tr("应用程序"),tr("无法读取文件%1: \n%2").arg(FileName).arg(locFile->errorString()));                return;            }        }else{            return;        }    }     qDebug() << "-----------BytesArray write newFile of start-----------";    if(recevBytes < totalBytes){        recevBytes += cClint->bytesAvailable();        //把缓存区的内容写入文件。        inBlock = cClint->readAll();        locFile->write(inBlock);        inBlock.resize(0);                             //清空缓存区    }    ui->progressBar->setMaximum(totalBytes);    ui->progressBar->setValue(recevBytes);//设置进度条的进度    double speed = recevBytes/useTime;    ui->label->setText(tr("(%1 m/s)").arg(speed));    qDebug() << "recevBytes:" << recevBytes;    qDebug() << "totalBytes:" << totalBytes;    if(recevBytes == totalBytes){        locFile->close();        cClint->close();        ui->label->setText(tr("接收文件 %1完毕 ").arg(FileName));    }} void Dialog::closeEvent(QCloseEvent *){    on_cClosebtn_clicked();} void Dialog::on_cCancelBtn_clicked(){    cClint->abort();    if(locFile->isOpen()){        locFile->close();    }} void Dialog::on_cClosebtn_clicked()       //关闭服务{    cClint->abort();    if(locFile->isOpen()){        locFile->close();    }    close();}//处理接收到的文件名void Dialog::hansPendingFile(QString serAddress,QString fileName){    QString cIpAddress = getIP(); //"192.168.31.119";    qDebug() << "cIpAddress:" << cIpAddress;    int btn = QMessageBox::information(this,tr("接收文件"),                                       tr("文件%1是否接收?").arg(fileName),                                       QMessageBox::Yes,QMessageBox::No);    if(btn == QMessageBox::Yes){        QString name = QFileDialog::getSaveFileName(0,tr("保存文件"),fileName);        if(!name.isEmpty()){            Dialog *clint = new Dialog(this);            setFileName(name);            setHostaddr(QHostAddress(serAddress));//默认一台电脑用。        }    }    else{       SendRefuse(refuse);        sleep(2);        on_cClosebtn_clicked();    }}QString Dialog::getIP(){    QList<QHostAddress> list = QNetworkInterface::allAddresses();    foreach (QHostAddress address, list) {        if(address.protocol() == QAbstractSocket::IPv4Protocol){            if(address.toString().contains("192.168.1")||address.toString().contains("127.0"))                continue;            return address.toString();           }    }    return 0;}//处理udp发送名字信号时函数void Dialog::processPendingDatarams(){    qDebug() << "pending Datarams......." ;    while(udpSocket->hasPendingDatagrams()){        QByteArray datagram;        datagram.resize(udpSocket->pendingDatagramSize());        udpSocket->readDatagram(datagram.data(), datagram.size());        QDataStream in(&datagram,QIODevice::ReadOnly);        QString time = QDateTime::currentDateTime()                .toString("yyyy-MM-dd hh:mm:ss");         //QString clientAddress, fileName;        QString fileName,serAddress;        in >> serAddress >>  fileName;        qDebug() << "pending fileName" << fileName;        hansPendingFile(serAddress,fileName);    }}void Dialog::SendRefuse(MessageType refuse){        QByteArray data;        QDataStream out(&data, QIODevice::WriteOnly);        out << refuse;        qDebug() << "data" << data;        int a= udpSocket->writeDatagram(data,data.length(),QHostAddress::LocalHost, u2port);        qDebug() << "------------writeDatagram a:" << a;        }void Dialog::displayError(QAbstractSocket::SocketError socketError){    switch(socketError)        {        //RemoteHostClosedError为远处主机关闭了连接时发出的错误信号        case QAbstractSocket::RemoteHostClosedError : break;        default : qDebug() << cClint->errorString();        }}


0 0
原创粉丝点击