Last active
February 17, 2019 00:01
-
-
Save lamprosg/4461154 to your computer and use it in GitHub Desktop.
TCP/IP Programming (Qt SDK)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void IP::connectToServer() //Connect to the server | |
{ | |
tcpSocket = new QTcpSocket(this); //Client socket constructor | |
tcpSocket->connectToHost("100.100.100.100", 3724); //Connect | |
//OR | |
//tcpSocket->connectToHost(QHostAddress::LocalHost,6178); | |
//The only QTcpSocket signals we need are QTcpSocket::readyRead(), | |
//signifying that data has been received, QTcpSocket::hostFound(), | |
//this signal is emitted after connectToHost() has been called and the host lookup has succeeded, | |
//and QTcpSocket::error(), which we will use to catch any connection errors | |
connect(tcpSocket, SIGNAL(hostFound()), this, SLOT(weAreConnected())); | |
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); | |
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(getFiles())); | |
connect(tcpSocket, SIGNAL(disconnected()), tcpSocket, SLOT(deleteLater())); | |
length=0; //Length of bytes read | |
counter=0; | |
newfile=true; | |
buffer=1024*1024; //A chunk of 1MB, we'll be used for buffering | |
offset = 0; | |
sizeread=0; | |
} | |
void IP::weAreConnected() | |
{ | |
ui->iplabel->setText("Connected"); | |
} | |
void IP::displayError(QAbstractSocket::SocketError socketError) | |
{ | |
switch (socketError) | |
{ | |
case QAbstractSocket::RemoteHostClosedError: | |
break; | |
case QAbstractSocket::HostNotFoundError: | |
QMessageBox::information(this, tr("IPShare Client"), | |
tr("The host was not found. Please check the " | |
"host name and make sure it is sharing.")); | |
break; | |
case QAbstractSocket::ConnectionRefusedError: | |
QMessageBox::information(this, tr("IPShare Client"), | |
tr("The connection was refused by the peer. " | |
"Make sure the other side is sharing, " | |
"and check that the host name and port " | |
"settings are correct.")); | |
break; | |
default: | |
QMessageBox::information(this, tr("IPShare Client"), | |
tr("The following error occurred: %1.") | |
.arg(tcpSocket->errorString())); | |
} | |
delete tcpSocket; | |
} | |
void IP::sendSomething() | |
{ | |
if (savedirectory=="/home/") | |
{ | |
QMessageBox::question(this, tr("Reminder"),tr("Select a directory for files to be saved first.")); | |
} | |
else | |
{ | |
QByteArray block; | |
QDataStream out(&block, QIODevice::WriteOnly); // we will serialize the data in the array block | |
out.setVersion(QDataStream::Qt_4_0); | |
out << (quint16)0; //we reserve space for a 16 bit integer that will contain the total size of the data block we are sending | |
out << QString( something ); //Sending the name of the file | |
out.device()->seek(0); //Going back to the beginning of the array | |
out << (quint16)(block.size() - sizeof(quint16)); //overwrite the reserved 16 bit integer value with the total size of the array | |
tcpSocket->write(block); //Send message | |
} | |
} | |
void IP::getFiles() //Receiving data | |
{ | |
//First get the filesize we're going to download | |
QDataStream in(tcpSocket); | |
in.setVersion(QDataStream::Qt_4_0); | |
quint64 blockSize=0; | |
/*******************Reading the blockSize first in order to know how much data we'll receive***/ | |
if (blockSize == 0) | |
{ | |
if (tcpSocket->bytesAvailable() < (int)sizeof(quint64)) | |
return; | |
in >> blockSize; | |
} | |
/**********************************************************************************************/ | |
if (tcpSocket->bytesAvailable() < (int) blockSize) //Wait until all the data are received | |
return; | |
in >> filesize; | |
QString path = savedirectory; | |
path += filenames[counter]; | |
file = new QFile(path); //Create the file | |
file->open(QIODevice::WriteOnly); //Open it | |
//Download it in chunks, so the memory won't crash | |
char *data = new char[buffer]; | |
length = tcpSocket->read(data, buffer); //Buffer 1MB first, max. | |
file->write(data,length); | |
sizeread += length; | |
int value = (sizeread/filesizes[counter])*100; | |
delete [] data; | |
if (sizeread == filesize) //File size reached, closing file | |
{ | |
file->close(); | |
delete file; | |
counter++; | |
length=0; | |
sizeread=0; | |
} | |
/*QTcpSocket::disconnectFromHost() will close the connection after QTcpSocket has finished writing | |
the data to the network. Because QTcpSocket works asynchronously, the data will be written after | |
this function returns, and control goes back to Qt's event loop. | |
The socket will then close, which in turn will cause QObject::deleteLater() to delete it.*/ | |
tcpSocket->disconnectFromHost(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***Client**************************************************************/ | |
QTcpSocket *tcpSocket; //Socket used by the client | |
bool iwantthem; //Distinguish between getting the list or the actual files | |
int numberofitems; //How many files are there | |
QString *filenames; //Individual file names | |
int filesize; //Individual file sizes | |
int totalfilesize; //Total size of files | |
qint64 length; //Length of bytes read | |
int counter; //File counter | |
bool newfile; | |
qint64 buffer; | |
QFile *file; | |
qint64 offset; | |
qint64 sizeread; | |
QString savedirectory; //Where files are going to be downloaded and saved | |
/***********************************************************************/ | |
/*Client Slots************************/ | |
void getFiles(); //Get the files | |
void displayError(QAbstractSocket::SocketError socketError); //Catch connection errors | |
void weAreConnected(); //When connection is established | |
/*************************************/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void IP::getAddresses() | |
{ | |
QNetworkInterface net; | |
QList<QHostAddress> addresses = net.allAddresses(); | |
QString text; | |
for (int i=0;i<addresses.size();i++) | |
{ | |
text+=addresses.value(i).toString(); | |
text+="\n\n"; | |
} | |
ui->textedit->setText(text); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
QT += core gui | |
QT += network |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void IP::sekectDir() | |
{ | |
savedirectory=QFileDialog::getExistingDirectory(this, tr("Select Directory"), | |
"/home", | |
QFileDialog::ShowDirsOnly | |
| QFileDialog::DontResolveSymlinks); | |
savedirectory += "/"; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void IP::serverStart() | |
{ | |
tcpServer = new QTcpServer(this); //tcpServer constructor | |
if (!tcpServer->isListening()) | |
{ | |
if (!tcpServer->listen(QHostAddress::Any, 3724)) //Start listening (WoW port) | |
{ | |
QMessageBox::critical(this, tr("IPShare Server"), | |
tr("Unable to start the server: %1.") | |
.arg(tcpServer->errorString())); | |
// close(); //Closes the widget | |
ui->iplabel->setText("Unable to start the server"); | |
tcpServer->close(); | |
delete tcpServer; | |
return; | |
} | |
//The QTcpServer::newConnection() signal is emitted each time a client connects to the server. | |
//The ServerRespond() function will be executed each time. | |
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(ServerRespond())); | |
} | |
} | |
void IP::ServerRespond() //First response to the client | |
{ | |
ui->iplabel->setText("Client connected"); | |
//we create a QByteArray and a QDataStream object, passing the bytearray to QDataStream's constructor | |
QByteArray block; | |
QDataStream out(&block, QIODevice::WriteOnly); // we will serialize the data in the array block | |
//We set the protocol version of QDataStream to QDataStream::Qt_4_0 to ensure that we can communicate with clients from future versions of Qt. | |
out.setVersion(QDataStream::Qt_4_0); | |
QString hello_there; | |
out << (quint64)0; //we reserve space for a 64 bit integer that will contain the total size of the data block we are sending | |
out << QString(hello_there); //Writing the bytearray | |
out.device()->seek(0); //Going back to the beginning of the array | |
out << (quint64)(block.size() - sizeof(quint64)); //overwrite the reserved 64 bit integer value with the total size of the array | |
/*We call QTcpServer::nextPendingConnection() to accept the connection | |
and use the returned QTcpSocket to communicate with the client.*/ | |
clientConnection = tcpServer->nextPendingConnection(); | |
clientConnection->write(block); //Sending the item list to the client | |
ui->iplabel->setText("File list sent"); | |
/*This signal is emitted once every time new data is available for reading from the device. | |
It will only be emitted again once new data is available, | |
such as when a new payload of network data has arrived on the network socket, | |
or when a new block of data has been appended to the device. | |
TCP is based on sending a stream of data, so we cannot expect to get the entire data in one go. | |
Especially on a slow network, the data can be received in several small fragments. | |
QTcpSocket buffers up all incoming data and emits readyRead() for every new block that arrives, | |
and it is our job to ensure that we have received all the data we need before we start parsing.*/ | |
connect(clientConnection, SIGNAL(readyRead()), this, SLOT(sendFiles())); | |
/*By connecting QTcpSocket::disconnected() to QObject::deleteLater(), | |
we ensure that the socket will be deleted after disconnecting.*/ | |
connect(clientConnection, SIGNAL(disconnected()), clientConnection, SLOT(deleteLater())); | |
} | |
void IP::sendFiles() | |
{ | |
//Read somethig and then send a file | |
quint16 blockSize=0; | |
QDataStream in(clientConnection); | |
in.setVersion(QDataStream::Qt_4_0); | |
/*******************Reading the blockSize first in order to know how much data we'll receive***/ | |
if (blockSize == 0) | |
{ | |
if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) | |
return; | |
in >> blockSize; | |
} | |
/**********************************************************************************************/ | |
if (clientConnection->bytesAvailable() < blockSize) //Wait until all the data are received | |
return; | |
QString messagefromclient; | |
in >> messagefromclient; | |
//Do something with the messagefronclient.... | |
//Sending a file | |
QFile *file= new QFile("file.dat"); | |
file->open(QIODevice::ReadOnly); | |
int filesize = file->size(); | |
//We'll send the file in chunks of 64k (short of). We don't want to fill the memory at once if it's a large file | |
qint64 chunk = 64000; | |
qint64 filepos=0; //Position for reading/writing | |
while (filepos < filesize) | |
{ | |
char *data = new char[chunk]; | |
qint64 length = file->read(data, chunk); | |
clientConnection->write(data,length); //Send read data | |
filepos += length; //Go to new position depending what we read | |
delete [] data; | |
} | |
file->close(); | |
delete file; //Free memory | |
/*QTcpSocket::disconnectFromHost() will close the connection after QTcpSocket has finished writing | |
the data to the network. Because QTcpSocket works asynchronously, the data will be written after | |
this function returns, and control goes back to Qt's event loop. | |
The socket will then close, which in turn will cause QObject::deleteLater() to delete it.*/ | |
// clientConnection->disconnectFromHost(); | |
} | |
void IP::serverStop() | |
{ | |
tcpServer->close(); | |
ui->iplabel->setText("Server closed"); | |
delete tcpServer; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <QString> | |
#include <QFileDialog> | |
#include <QMessageBox> | |
#include <QTcpServer> | |
/***Server**************************************************************/ | |
QTcpServer *tcpServer; // Server! | |
QTcpSocket *clientConnection; // Serverwise Socket for communication with the client | |
/***********************************************************************/ | |
/*Server Slots************************/ | |
void ServerRespond(); //Server response to connected clients | |
void sendFiles(); //Gets the requested file for uploading and sends it | |
/*************************************/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment