File transfer using the TCP protocol in QT (can be looped in one direction)

Source: Internet
Author: User
Tags file size socket


The approximate steps are as follows:



1, the server-side settings monitoring socket, start monitoring;



2, the client begins to transfer the file when the connection is successful, there is a connected () Signal connection send () slot, send () sends the header information, including the file name, the total file size and filename size, etc.;



3, the transmission of the file header information began to transfer the contents of the file, there is a byteswritten (Qint64) signal connected to the Goonsend (Qint64) slot, the former is when you want to write data sockets will start signal, that is, when you want to write data sockets, continue to transmit data, there is send () sends the header information to start triggering until the file is passed.



4, on the server side, the first to receive the file header information, and then read the filename to open a file with a new file, and then read the file name is the size of the files, to update the progress bar and continue to receive data;



5, the realization of cyclic transmission, in the client, because the first send () is triggered by the connected () signal, after each transfer should be manually call send (), on the server side, when there is new data arrives, will determine whether the header file, Therefore, each time the file is passed the bytereceived reset to 0, that is, the next time to receive data when the result of bytereceived judgment is a new file.



On the code bar, some object names and function names are not good, comments should be able to make people understand.






Client code:



Widget.h





#ifndef widget_h
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QFile>
#include <string>

namespace Ui {
class Widget;
}

Class Widget:public Qwidget
{
    q_object public

:
    explicit Widget (Qwidget *parent = 0);
    ~widget ();
    
Private:
    ui::widget *ui;

    Qtcpsocket *tcpclient;
    QFile *localfile;
    QString FileName;  FileName

    qbytearray outblock;  Qint64 Loadsize of Sub-pass
    ;  The size of each send data
    qint64 bytetowrite;  The remaining data size
    Qint64 totalsize;  Total file size

    int sendtimes;  Used to mark whether to send for the first time, after the first connection signal is triggered, followed by manually calling

private slots:
    void Send ();  Transfer file header information
    void Goonsend (Qint64);  Transfer file contents
    void on_openpushbutton_clicked ();
    void on_sendpushbutton_clicked ();
};

#endif//Widget_h

Widget.cpp




#include "widget.h"
#include "ui_widget.h"
#include <QHostAddress>
#include <QTextCodec>
#include <QFileDialog>

Widget :: Widget (QWidget * parent):
    QWidget (parent),
    ui (new Ui :: Widget)
{
    ui-> setupUi (this);

    ui-> progressLabel-> hide ();

    QTextCodec :: setCodecForTr (QTextCodec :: codecForName ("GBK"));

    tcpClient = new QTcpSocket (this);
    sendTimes = 0;

    connect (tcpClient, SIGNAL (connected ()), this, SLOT (send ())); // When the connection is successful, start to transfer files
    connect (tcpClient, SIGNAL (bytesWritten (qint64)), this, SLOT (goOnSend (qint64)));


}

void Widget :: send () // Send file header information
{
    byteToWrite = localFile-> size (); // The size of the remaining data
    totalSize = localFile-> size ();

    loadSize = 4 * 1024; // The size of data sent each time

    QDataStream out (& outBlock, QIODevice :: WriteOnly);
    QString currentFileName = fileName.right (fileName.size ()-fileName.lastIndexOf ('/')-1);

    out << qint64 (0) << qint64 (0) << currentFileName;

    totalSize + = outBlock.size (); // The total size is the file size plus the size of the file name and other information
    byteToWrite + = outBlock.size ();

    out.device ()-> seek (0); // Go back to the beginning of the byte stream to write a qint64 in front, which is the total size and file name and other information size
    out << totalSize << qint64 (outBlock.size ());

    tcpClient-> write (outBlock); // Send the read file to the socket

    ui-> progressLabel-> show ();
    ui-> sendProgressBar-> setMaximum (totalSize);
    ui-> sendProgressBar-> setValue (totalSize-byteToWrite);
}

void Widget :: goOnSend (qint64 numBytes) // Start sending file content
{
    byteToWrite-= numBytes; // Remaining data size
    outBlock = localFile-> read (qMin (byteToWrite, loadSize));
    tcpClient-> write (outBlock);

    ui-> sendProgressBar-> setMaximum (totalSize);
    ui-> sendProgressBar-> setValue (totalSize-byteToWrite);

    if (byteToWrite == 0) // Send completed
        ui-> sendStatusLabel-> setText (tr ("File sending completed!"));
}

Widget :: ~ Widget ()
{
    delete ui;
}

void Widget :: on_openPushButton_clicked () // Open the file and get the file name (including path)
{
    ui-> sendStatusLabel-> setText (tr ("Opening file ..."));
    ui-> sendProgressBar-> setValue (0); // Not sent for the first time

    loadSize = 0;
    byteToWrite = 0;
    totalSize = 0;
    outBlock.clear ();

    fileName = QFileDialog :: getOpenFileName (this);
    localFile = new QFile (fileName);
    localFile-> open (QFile :: ReadOnly);

    ui-> sendStatusLabel-> setText (tr ("File% 1 opened"). arg (fileName));
}

void Widget :: on_sendPushButton_clicked ()
{
    if (sendTimes == 0) // Only the first time it is sent, it happens when the connection generates the signal connect
    {
        tcpClient-> connectToHost (QHostAddress ("172.19.198.43"), 10000);
        sendTimes = 1;
    }
    else
        send (); // When sending for the first time, connectToHost initiates the connect signal to call send, and you need to call send after the second time

    ui-> sendStatusLabel-> setText (tr ("Sending file% 1"). arg (fileName));
}


Service-Side code:



Widget.h





#ifndef widget_h
#define WIDGET_H

#include <QWidget>
#include <QtNetwork/QTcpServer>
# Include <QtNetwork/QTcpSocket>
#include <QFile>
#include <QString>

namespace Ui {
class Widget;
}

Class Widget:public Qwidget
{
    q_object public
    
:
    explicit Widget (Qwidget *parent = 0);
    ~widget ();
    
Private:
    ui::widget *ui;

    Qtcpserver *server;
    Qtcpsocket *receivedsocket;
    QFile *newfile;

    Qbytearray Inblock;
    QString FileName;
    Qint64 totalsize;  Total file size to send (file contents & filename information)
    Qint64 bytereceived;  The size that has been sent

private slots:
    void Acceptconnection ();
    void ReadClient ();
    void on_pushbutton_clicked ();
};

#endif//Widget_h





Widget.cpp





#include "widget.h"
#include "ui_widget.h"
#include <QTextCodec>

Widget :: Widget (QWidget * parent):
    QWidget (parent),
    ui (new Ui :: Widget)
{
    ui-> setupUi (this);
    ui-> progressLabel-> hide ();
    QTextCodec :: setCodecForTr (QTextCodec :: codecForName ("GBK"));
}

void Widget :: acceptConnection ()
{
    ui-> receivedStatusLabel-> setText (tr ("Connected, preparing to receive files!"));

    receivedSocket = server-> nextPendingConnection ();
    connect (receivedSocket, SIGNAL (readyRead ()), this, SLOT (readClient ()));
}

void Widget :: readClient ()
{
    ui-> receivedStatusLabel-> setText (tr ("Receiving file ..."));

    if (byteReceived == 0) // just started to receive data, this data is file information
    {
        ui-> receivedProgressBar-> setValue (0);

        QDataStream in (receivedSocket);
        in >> totalSize >> byteReceived >> fileName;
        fileName = "Files /" + fileName;
        newFile = new QFile (fileName);
        newFile-> open (QFile :: WriteOnly);
    }
    else // Officially read the file content
    {
        inBlock = receivedSocket-> readAll ();

        byteReceived + = inBlock.size ();
        newFile-> write (inBlock);
        newFile-> flush ();
    }

    ui-> progressLabel-> show ();
    ui-> receivedProgressBar-> setMaximum (totalSize);
    ui-> receivedProgressBar-> setValue (byteReceived);

    if (byteReceived == totalSize)
    {
        ui-> receivedStatusLabel-> setText (tr ("% 1receive completed"). arg (fileName));

        inBlock.clear ();
        byteReceived = 0;
        totalSize = 0;
    }
}

Widget :: ~ Widget ()
{
    delete ui;
}

void Widget :: on_pushButton_clicked ()
{
    totalSize = 0;
    byteReceived = 0;

    server = new QTcpServer (this);
    server-> listen (QHostAddress ("172.19.198.43"), 10000);

    connect (server, SIGNAL (newConnection ()), this, SLOT (acceptConnection ()));

    ui-> receivedProgressBar-> setValue (0);
    ui-> receivedStatusLabel-> setText (tr ("Start listening ..."));
}






Then check the files that are received in the folder.








Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.