first, the client
In the client to connect with the server, once the connection is successful, will issue a connected () signal, then the file sent.
When sending data, we first send the size information of the data. This time, we want to first send the total size of the file, then the file name length, then the file name, these three parts we are called the file header structure, and finally send the file data. So in the sending function we have to do the corresponding processing, of course, in the server's receive function we also have to do the corresponding processing. For file size, this time we used the Qint64, which is 64-bit, can represent a very large file.
1. In the previous section, we created a new project to name the project "Tcpsender". Note Add the network module.
2. We design the interface in the Widget.ui file as follows.
Here "host" after the line edit objectname for Hostlineedit, "Port" after the line edit objectname for Portlineedit; The following progress The objectname of Bar is Clientprogressbar, its Value property is set to 0, the objetname of State label is Clientstatuslabel; The objectname of the button is Openbutton; the objectname of the "Send" button is Sendbutton;
3. Make changes in the Widget.h file.
(1) Add header file #include <QtNetwork>
(2) Add private variable:
Qtcpsocket *tcpclient;
Qfile *localfile; The file to send
Qint64 totalbytes; Total data size
Qint64 Byteswritten; Data size has been sent
Qint64 Bytestowrite; Remaining data size
Qint64 loadsize; The size of the data sent each time
QString FileName; Save File path
Qbytearray Outblock; Data buffer, which holds the data to be sent every time
(3) Adding a private slot function:
Private Slots:
void Send (); Connecting to a server
void Starttransfer (); Send file size and other information
void Updateclientprogress (Qint64); Send data, update progress bar
Voiddisplayerror (Qabstractsocket::socketerror); Display Error
void OpenFile (); Open File
4. Make changes in the Widget.cpp file.
Add header file: #include <QFileDialog>
(1) Add code to the constructor:
Loadsize = 4*1024;
totalbytes = 0;
Byteswritten = 0;
Bytestowrite = 0;
TcpClient = new Qtcpsocket (this);
Connect (tcpclient,signal (connected ()), This,slot (Starttransfer ()));
When the connection server is successful, the connected () signal is sent and we begin to transfer the file
Connect (tcpclient,signal (Byteswritten (Qint64)), this,
SLOT (Updateclientprogress (Qint64)));
When data is sent successfully, we update the progress bar
Connect (tcpclient,signal error (Qabstractsocket::socketerror)), this,
SLOT (DisplayError (Qabstractsocket::socketerror)));
Ui->sendbutton->setenabled (FALSE);
Start making the Send button unavailable
We mainly carry out the initialization of variables and the correlation of several signal and slot functions.
(2) Implement open File function.
void Widget::openfile ()//Open File
{
FileName =qfiledialog::getopenfilename (this);
if (!filename.isempty ())
{
Ui->sendbutton->setenabled (TRUE);
Ui->clientstatuslabel->settext (TR ("Open file%1 succeeded.) ”)
. Arg (fileName));
}
}
The function is called in the event slot function by clicking the Open button below.
(3) Implement the connection function.
void Widget::send ()//Connect to server, perform send
{
Ui->sendbutton->setenabled (FALSE);
Byteswritten = 0;
Initialize sent bytes to 0
Ui->clientstatuslabel->settext (tr ("Connected ..."));
Tcpclient->connecttohost (Ui->hostlineedit->text (),
Ui->portlineedit->text (). ToInt ());//Connection
}
The function is called in the Click event Slot function of the Send button.
(4) Implementation of the file header structure sent.
void Widget::starttransfer ()//to deliver information such as file size
{
LocalFile = new Qfile (fileName);
if (!localfile->open (qfile::readonly))
{
Qdebug () << "Open File error!";
Return
}
TotalBytes = Localfile->size ();
Total File Size
Qdatastreamsendout (&outblock,qiodevice::writeonly);
Sendout.setversion (Qdatastream::qt_4_6);
QString currentfilename =filename.right (filename.size ()-Filename.lastindexof ('/')-1);
Sendout << qint64 (0) <<qint64 (0) << currentfilename;
Write the total size information space, file name size information space, filename
TotalBytes + + outblock.size ();
The total size here is the sum of information such as file name size and actual file size
Sendout.device ()->seek (0);
Sendout<<totalbytes<<qint64 ((outblock.size ()-sizeof (Qint64) *2));
Returns the start of the Outbolock, replacing two qint64 (0) space with actual size information
Bytestowrite = Totalbytes-tcpclient->write (Outblock);
The size of the remaining data after sending the header data
Ui->clientstatuslabel->settext (tr ("Connected"));
Outblock.resize (0);
}
(5) The following is the update progress bar, which is to send file data.
void Widget::updateclientprogress (Qint64 numbytes)//Update progress bar to implement file transfer
{
Byteswritten + = (int) numbytes;
The size of the data that has been sent
if (Bytestowrite > 0)//If data has been sent
{
Outblock =localfile->read (Qmin (bytestowrite,loadsize));
Each time you send the loadsize size data, this is set to 4KB, if the remaining data is less than 4KB,
The size of the remaining data is sent
bytestowrite-= (int) tcpclient->write (outblock);
The size of the remaining data after sending the data once
Outblock.resize (0);
Empty Send buffer
}
Else
{
Localfile->close (); If no data is sent, close the file
}
Ui->clientprogressbar->setmaximum (totalbytes);
Ui->clientprogressbar->setvalue (Byteswritten);
Update progress bar
if (Byteswritten = = totalbytes)//Send complete
{
Ui->clientstatuslabel->settext (TR ("Transfer file%1 succeeded"). Arg (fileName));
Localfile->close ();
Tcpclient->close ();
}
}
(6) Implement error handling function.
void Widget::d isplayerror (qabstractsocket::socketerror)//Display Error
{
Qdebug () <<tcpclient->errorstring ();
Tcpclient->close ();
Ui->clientprogressbar->reset ();
Ui->clientstatuslabel->settext (TR ("Client Ready"));
Ui->sendbutton->setenabled (TRUE);
}
(7) We proceed from the Widget.ui to the "open" button and the "Send" button of the Click event Slot function, and then change the following.
void widget::on_openbutton_clicked ()//Open button
{
OpenFile ();
}
void widget::on_sendbutton_clicked ()//Send button
{
Send ();
}
5. In order to make the program in Chinese does not display garbled, in the main.cpp file changes.
Add header file: #include <QTextCodec>
Add code to the main function: Qtextcodec::setcodecfortr (Qtextcodec::codecforlocale ()); Code:
Engineering documents
#-------------------------------------------------
#
# Project created by Qtcreator 2014-09-28t19:45:50
#
#-------------------------------------------------
QT + + core GUI
QT + + Network
GreaterThan (Qt_major_version, 4): QT + = Widgets
TARGET = Tcpsender
TEMPLATE = App
SOURCES + + main.cpp\
Widget.cpp
HEADERS + + widget.h
FORMS + widget.ui
Wiget.h header File
#ifndef Widget_h
#define Widget_h
#include <QWidget>
#include <QtNetwork>
#include <QTcpServer>
#include <QTcpSocket>
#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>
#include <QTextCodec>
#include <QAbstractSocket>
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; The file to send
Qint64 totalbytes; Total data size
Qint64 Byteswritten; The size of the data that has been sent
Qint64 Bytestowrite; Remaining data size
Qint64 loadsize; The size of the data sent each time
QString FileName; Save File path
Qbytearray Outblock; Data buffer, which holds the data to be sent every time
Private Slots:
void Send (); Connecting to a server
void Starttransfer (); Send file size and other information
void Updateclientprogress (Qint64); Send data, update progress bar
void DisplayError (Qabstractsocket::socketerror socketerror); Display Error
void OpenFile (); Open File
void on_openbutton_clicked ();
void on_sendbutton_clicked ();
};
#endif//Widget_h
Main.cpp
#include "Widget.h"
#include <QApplication>
int main (int argc, char *argv[])
{
Qapplication A (argc, argv);
Widget W;
/* Qtextcodec::setcodecforlocale (Qtextcodec::codecforname ("UTF-8"));
qtextcodec::setcodecforcstrings (Qtextcodec::codecforname ("UTF-8"));
QTEXTCODEC::SETCODECFORTR (Qtextcodec::codecforname ("UTF-8"));
Qtextcodec::setcodecforlocale (Qtextcodec::codecforname ("GB18030"));
QTEXTCODEC::SETCODECFORTR (Qtextcodec::codecforlocale ());
W.show ();
return A.exec ();
}
Widget.cpp file
#include "Widget.h"
#include "Ui_widget.h"
Widget::widget (Qwidget *parent):
Qwidget (parent),
UI (New Ui::widget)
{
UI->SETUPUI (this);
Loadsize = 4*1024;
totalbytes = 0;
Byteswritten = 0;
Bytestowrite = 0;
TcpClient = new Qtcpsocket (this);
Connect (tcpclient,signal (connected ()), This,slot (Starttransfer ()));
When the connection server is successful, the connected () signal is sent and we begin to transfer the file
Connect (tcpclient,signal (Bytewritten (Qint64)), This,slot (Updateclientprogress (Qint64));
When data is sent successfully, we update the progress bar
Connect (tcpclient,signal (qabstractsocket::socketerror), This,slot (DisplayError (abstractsocket:: SocketError)));
Ui->sendbutton->setenabled (FALSE);
The Send button is not available at the beginning
}
Widget::~widget ()
{
Delete UI;
}
void Widget::openfile ()
{
FileName = Qfiledialog::getopenfilename (this);
if (!filename.isempty ())
{