Qt?TCP網(wǎng)絡(luò)通信學(xué)習(xí)
TCP簡(jiǎn)介:
Transmission Control Protocol,傳輸控制協(xié)議 。用于數(shù)據(jù)傳輸?shù)牡蛯泳W(wǎng)絡(luò)協(xié)議,多個(gè)物聯(lián)網(wǎng)協(xié)議都是基于TCP協(xié)議的。它是一個(gè)面向數(shù)據(jù)流和連接的可靠傳輸協(xié)議。
TCP頭部格式:

QTcpSocket類為TCP提供了一個(gè)接口,繼承自QAbstractSocket??蓪?shí)現(xiàn)POP3、SMTP、NNTP等標(biāo)準(zhǔn)的網(wǎng)絡(luò)協(xié)議,也可以實(shí)現(xiàn)自定義的網(wǎng)絡(luò)協(xié)議。異步工作,依靠事件循環(huán)來(lái)檢測(cè)到來(lái)的數(shù)據(jù),并且自動(dòng)刷新輸出的數(shù)據(jù)。而QAbstractSocket繼承自QIODevice,故該類具備文件的讀寫功能,可以使用QTextStream和QDataStream。
QHostAddress QAbstractSocket::peerAddress () const 獲取主機(jī)的IP地址
quint16 QAbstractSocket::peerPort () const 獲取主機(jī)的端口號(hào)
qint64 QIODevice::write ( const QByteArray & byteArray ) //寫入數(shù)據(jù),即通過(guò)TCP發(fā)送數(shù)據(jù)。
QByteArray QIODevice::read ( qint64 maxSize ) //讀取數(shù)據(jù),最多讀取maxSize。即獲取TCP接收的存放在緩沖區(qū)的數(shù)據(jù)
QByteArray QIODevice::readAll () //獲取TCP存放在緩沖區(qū)可讀取的所有數(shù)據(jù)。
從一個(gè)QTcpSocket中讀取數(shù)據(jù)前,必須先調(diào)用qint64 QIODevice::bytesAvailable () const 函數(shù)來(lái)確保已經(jīng)有足夠的數(shù)據(jù)可用。
涉及到的信號(hào):
void QAbstractSocket::connected () [signal] 當(dāng)連接建立成功發(fā)射連接信號(hào),指示一個(gè)已建立的新連接。
void QAbstractSocket::error ( QAbstractSocket::SocketError socketError ) [signal] 連接發(fā)生了錯(cuò)誤,就會(huì)發(fā)送error()信號(hào),參數(shù)指示發(fā)生了什么錯(cuò)誤。
void QAbstractSocket::disconnected () [signal] 斷開(kāi)一個(gè)已經(jīng)存在的連接時(shí),發(fā)射斷開(kāi)信號(hào)。
void QAbstractSocket::stateChanged ( QAbstractSocket::SocketState socketState ) [signal] 狀態(tài)改變都會(huì)發(fā)射stateChanged()信號(hào)。
void QIODevice::bytesWritten ( qint64 bytes ) [signal] 表示數(shù)據(jù)寫入完成,對(duì)應(yīng)的可以調(diào)用bytesToWrite()方法了解寫入了多少字節(jié)的數(shù)據(jù)。
void QIODevice::readyRead () [signal] 表示有數(shù)據(jù)可以讀取,對(duì)應(yīng)的可以調(diào)用bytesAvailable()方法了解可以讀取多少字節(jié)的數(shù)據(jù)。
一個(gè)簡(jiǎn)單的TCP客戶端和服務(wù)端程序,單連接。
客戶端程序:
#ifndef QTTCPCLIENT_H
#define QTTCPCLIENT_H
?
#include <QObject>
#include <QAbstractSocket>
?
class QTcpSocket; //前置聲明
?
//客戶端程序 ?單連接,即一個(gè)客戶端一個(gè)服務(wù)端
class QtTcpClient : public QObject
{
? ? Q_OBJECT
public:
? ? explicit QtTcpClient(QObject *parent = 0);
? ? ~QtTcpClient();
?
? ? void sendMessage(); //發(fā)送信息
?
private slots:
? ? void readMessage(); ?//獲取返回的信息
? ? void displayError(QAbstractSocket::SocketError); ?//獲取連接發(fā)生的錯(cuò)誤
?
?
private:
?
? ? QTcpSocket *tcpSocket; ?//tcp連接
?
? ? quint16 blockSize; ?//發(fā)送數(shù)據(jù)的大小
};
?
#endif // QTTCPCLIENT_H
#include "qttcpclient.h"
#include <QtNetwork>
#include <QDataStream>
#include <QString>
#include <QByteArray>
#include <QIODevice>
#include <QObject>
#include <QDebug>
?
QtTcpClient::QtTcpClient(QObject *parent) :
? ? QObject(parent)
{
? ? tcpSocket=new QTcpSocket(this);
? ? //建立信號(hào)連接,readyRead表示有數(shù)據(jù)過(guò)來(lái),需要讀取
? ? connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessage()));
? ? //建立信號(hào)連接,error(QAbstractSocket::SocketError)連接發(fā)生錯(cuò)誤或關(guān)閉時(shí)會(huì)發(fā)射此信號(hào)
? ? connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
?
? ? blockSize=0;
? ? tcpSocket->abort();//終止已有的連接
?
? ? tcpSocket->connectToHost(QHostAddress(QString("127.0.0.1")),6666);//建立新的連接
?
? ? qDebug()<<"client run......"<<endl;
}
?
QtTcpClient::~QtTcpClient()
{
? ? delete tcpSocket;
? ? tcpSocket=NULL;
}
?
void QtTcpClient::sendMessage()
{
? ? QByteArray block;
? ? QDataStream out(&block,QIODevice::WriteOnly);
?
? ? out.setVersion(QDataStream::Qt_4_0);
? ? out<<(quint16)0;
? ? out<<QString("hi server this is my first connect!!!");
? ? out.device()->seek(0);//定位到數(shù)據(jù)的開(kāi)頭
? ? out<<(quint16)(block.size()-sizeof(quint16)); //添加數(shù)據(jù)大小信息到數(shù)據(jù)開(kāi)頭
?
? ? tcpSocket->write(block); //發(fā)送數(shù)據(jù)
?
}
?
void QtTcpClient::readMessage()
{
? ? QString message;
? ? QDataStream in(tcpSocket);
? ? in.setVersion(QDataStream::Qt_4_0);
?
? ? if(blockSize==0)
? ? {
? ? ? ? //判斷接收的數(shù)據(jù)是否大于兩字節(jié),也就是文件的大小信息所占的空間
? ? ? ? //如果是則保存到blockSize中,否則直接返回,繼續(xù)接收數(shù)據(jù)。
? ? ? ? if(tcpSocket->bytesAvailable()<(int)sizeof(quint16))
? ? ? ? {
? ? ? ? ? ? return;
? ? ? ? }
?
? ? ? ? in>>blockSize;
? ? }
? ? //如果沒(méi)有接收完全部數(shù)據(jù),則返回繼續(xù)接收
? ? if(tcpSocket->bytesAvailable()<blockSize)
? ? {
? ? ? ? return;
? ? }
? ? //將接收的數(shù)據(jù)存放到變量中
? ? in>>message;
?
? ? qDebug()<<message;
?
? ? this->sendMessage();
?
? ? //斷開(kāi)連接
? ? tcpSocket->disconnectFromHost();
}
?
void QtTcpClient::displayError(QAbstractSocket::SocketError)
{
? ? switch(tcpSocket->error())
? ? {
? ? case QAbstractSocket::RemoteHostClosedError: ?//遠(yuǎn)程服務(wù)端關(guān)閉連接錯(cuò)誤
? ? ? ? tcpSocket->disconnectFromHost();
? ? ? ? qDebug()<<"client close now";
? ? ? ? break;
? ? default:
? ? ? ? qDebug()<<"error id: "<<tcpSocket->error()<<endl;
? ? ? ? qDebug()<<"error message: "<<tcpSocket->errorString()<<endl;
? ? ? ? break;
? ? }
}
?
#include <QCoreApplication>
#include "qttcpclient.h"
?
int main(int argc, char *argv[])
{
? ? QCoreApplication a(argc, argv);
?
? ? QtTcpClient tcpclient_t;
? ??
? ? return a.exec();
}服務(wù)端程序:
#ifndef QTTCPSERVER_H
#define QTTCPSERVER_H
?
#include <QObject>
#include <QAbstractSocket>
?
class QTcpServer; //前置聲明
class QTcpSocket;
?
//服務(wù)端程序 ?單連接,即一個(gè)客戶端一個(gè)服務(wù)端
class QtTcpServer : public QObject
{
? ? Q_OBJECT
public:
? ? explicit QtTcpServer(QObject *parent = 0);
? ? ~QtTcpServer();
?
private slots:
? ? void sendMessage();//發(fā)送信息
? ? void readMessage();//獲取返回的信息
? ? void displayError(QAbstractSocket::SocketError);//獲取連接發(fā)生的錯(cuò)誤
?
private:
? ? QTcpServer *tcpServer; //tcp服務(wù)端
?
? ? QTcpSocket *clientConnect;//來(lái)自客戶端的連接
? ? quint16 blockSize; ?//接收數(shù)據(jù)的大小
};
?
#endif // QTTCPSERVER_H
?
?
#include "qttcpserver.h"
#include <QtNetwork>
#include <QDataStream>
#include <QString>
#include <QByteArray>
#include <QIODevice>
#include <QObject>
#include <QDebug>
?
QtTcpServer::QtTcpServer(QObject *parent) :
? ? QObject(parent)
{
? ? blockSize=0;
? ? tcpServer=new QTcpServer(this);
?
? ? //開(kāi)始監(jiān)聽(tīng)
? ? if(!tcpServer->listen(QHostAddress(QString("127.0.0.1")),6666))
? ? {
? ? ? ? qDebug()<<tcpServer->serverError()<<endl;
? ? ? ? qDebug()<<tcpServer->errorString()<<endl;
? ? ? ? qApp->exit();
? ? }
? ? //建立信號(hào)連接,每來(lái)一個(gè)新的連接,就發(fā)送服務(wù)端信息
? ? connect(tcpServer,SIGNAL(newConnection()),this,SLOT(sendMessage()));
?
? ? qDebug()<<"server run....."<<endl;
}
?
QtTcpServer::~QtTcpServer()
{
? ? delete tcpServer;
? ? tcpServer=NULL;
?
? ? delete clientConnect;
? ? clientConnect=NULL;
}
?
void QtTcpServer::sendMessage()
{
? ? QByteArray block;
? ? QDataStream out(&block,QIODevice::WriteOnly);
?
? ? out.setVersion(QDataStream::Qt_4_0);
? ? out<<(quint16)0;
? ? out<<QString("hello client the connect build!!!");
? ? out.device()->seek(0);
? ? out<<(quint16)(block.size()-sizeof(quint16));
?
? ? clientConnect=tcpServer->nextPendingConnection();//獲取客戶端的連接
? ? tcpServer->close();
?
? ? //關(guān)聯(lián)套接字的disconnected()和deleteLater(),表明當(dāng)連接斷開(kāi)時(shí)刪除該套接字
? ? connect(clientConnect,SIGNAL(disconnected()),clientConnect,SLOT(deleteLater()));
?
? ? clientConnect->write(block);
?
? ? connect(clientConnect,SIGNAL(readyRead()),this,SLOT(readMessage()));
? ? connect(clientConnect,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
?
}
?
void QtTcpServer::readMessage()
{
? ? QString message;
? ? QDataStream in(clientConnect);
? ? in.setVersion(QDataStream::Qt_4_0);
?
? ? if(blockSize==0)
? ? {
? ? ? ? if(clientConnect->bytesAvailable()<(int)sizeof(quint16))
? ? ? ? {
? ? ? ? ? ? return;
? ? ? ? }
?
? ? ? ? in>>blockSize;
? ? }
?
? ? if(clientConnect->bytesAvailable()<blockSize)
? ? {
? ? ? ? return;
? ? }
?
? ? in>>message;
?
? ? qDebug()<<message;
?
}
?
void QtTcpServer::displayError(QAbstractSocket::SocketError)
{
? ? switch(clientConnect->error())
? ? {
? ? case QAbstractSocket::RemoteHostClosedError:
? ? ? ? clientConnect->disconnectFromHost(); //disconnectFromHost函數(shù)會(huì)一直等待套接字將所有數(shù)據(jù)發(fā)送完畢,然后關(guān)閉該套接字,并發(fā)射disconnected信號(hào)
? ? ? ? qDebug()<<"server connect close"<<endl;
? ? ? ? break;
? ? default:
? ? ? ? qDebug()<<"error id: "<<clientConnect->error()<<endl;
? ? ? ? qDebug()<<"error message: "<<clientConnect->errorString()<<endl;
? ? ? ? clientConnect->disconnectFromHost();
? ? ? ? qDebug()<<"server connect close"<<endl;
? ? ? ? break;
? ? }
}
?
#include <QCoreApplication>
#include "qttcpserver.h"
?
int main(int argc, char *argv[])
{
? ? QCoreApplication a(argc, argv);
?
? ? QtTcpServer tcpserver_t;
? ??
? ? return a.exec();
}運(yùn)行結(jié)果:

基于TCP的文件傳輸程序:
客戶端程序:
#ifndef CLIENT_H
#define CLIENT_H
#include <QAbstractSocket>
#include <QDialog>
#include <QFile>
#include <QTcpSocket>
#include <QString>
#include <QByteArray>
?
namespace Ui {
class Client;
}
?
class Client : public QDialog
{
? ? Q_OBJECT
? ??
public:
? ? explicit Client(QWidget *parent = 0);
? ? ~Client();
?
private slots:
? ? void openFile();
? ? void send();
? ? void startTransfer();
? ? void updateClientProgress(qint64);
? ? void displayError(QAbstractSocket::SocketError);
? ??
? ? void on_pushButton_open_clicked();
? ? void on_pushButton_send_clicked();
?
private:
? ? Ui::Client *ui;
?
? ? QTcpSocket *tcpClient; //tcp連接
? ? QFile *localFile; ? ? ?//要發(fā)送的文件
? ? qint64 totalBytes; ? ? //發(fā)送數(shù)據(jù)的總大小
? ? qint64 bytesWritten; ? //已經(jīng)發(fā)送的數(shù)據(jù)大小
? ? qint64 bytesToWrite; ? //剩余的數(shù)據(jù)大小
? ? qint64 payloadSize; ? ?//每次發(fā)送數(shù)據(jù)的大小
? ? QString fileName; ? ? ?//保存文件路徑
? ? QByteArray outBlock; ? //數(shù)據(jù)緩沖區(qū),即存放每次要發(fā)送的數(shù)據(jù)塊
};
?
#endif // CLIENT_H
?
?
#include "client.h"
#include "ui_client.h"
#include <QtNetwork>
#include <QFileDialog>
#include <QDebug>
?
Client::Client(QWidget *parent) :
? ? QDialog(parent),
? ? ui(new Ui::Client)
{
? ? ui->setupUi(this);
?
? ? //初始化變量
? ? this->payloadSize=64*1024; ? //64KB,每次發(fā)送的數(shù)據(jù)塊大小為64KB
? ? this->totalBytes=0;
? ? this->bytesWritten=0;
? ? this->bytesToWrite=0;
?
? ? this->tcpClient=new QTcpSocket(this);
?
? ? //當(dāng)連接服務(wù)器成功時(shí),發(fā)送connected()信號(hào),開(kāi)始傳送文件
? ? connect(this->tcpClient,SIGNAL(connected()),this,SLOT(startTransfer()));
? ? //每次發(fā)送成功后發(fā)送bytesWritten(qint64))信號(hào),告訴已成功發(fā)送的數(shù)據(jù)塊大小,并更新進(jìn)度條
? ? connect(this->tcpClient,SIGNAL(bytesWritten(qint64)),this,SLOT(updateClientProgress(qint64)));
? ? //接收tcp連接發(fā)生的錯(cuò)誤
? ? connect(this->tcpClient,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
?
? ? ui->pushButton_send->setEnabled(false);
}
?
Client::~Client()
{
? ? delete ui;
}
?
void Client::openFile()
{
? ? this->fileName=QFileDialog::getOpenFileName(this);
? ? if(!this->fileName.isEmpty())
? ? {
? ? ? ? ui->pushButton_send->setEnabled(true);
? ? ? ? ui->label_state->setText(QString("打開(kāi)文件 %1 成功").arg(this->fileName));
? ? }
}
?
void Client::send()
{
? ? ui->pushButton_send->setEnabled(false);
?
? ? this->bytesWritten=0;
? ? ui->label_state->setText(QString("連接中..."));
? ? //連接服務(wù)器
? ? this->tcpClient->connectToHost(ui->lineEdit_host->text(),ui->lineEdit_port->text().toInt());
}
?
void Client::startTransfer()
{
? ? this->localFile=new QFile(this->fileName);
? ? //打開(kāi)文件
? ? if(!this->localFile->open(QFile::ReadOnly))
? ? {
? ? ? ? qDebug()<<"client: open file error!"<<endl;
? ? ? ? return;
? ? }
?
? ? //獲取打開(kāi)文件的大小
? ? this->totalBytes=this->localFile->size();
?
? ? QDataStream sendOut(&this->outBlock,QIODevice::WriteOnly);
? ? sendOut.setVersion(QDataStream::Qt_4_0);
? ? //獲取文件名(去掉文件前面的路徑)
? ? QString currentFileName=this->fileName.right(this->fileName.size()-this->fileName.lastIndexOf('/')-1);
? ? //保留總大小信息空間,文件名大小信息空間,然后輸入文件名
? ? sendOut<<qint64(0)<<qint64(0)<<currentFileName;
? ? //總大小變量為總大小信息、文件名大小信息、文件名和實(shí)際文件大小的總和
? ? this->totalBytes+=this->outBlock.size();
? ? //返回outBlock的開(kāi)始,填入總大小信息
? ? sendOut.device()->seek(0);
? ? //填入各個(gè)項(xiàng)的大小信息以及文件名
? ? sendOut<<this->totalBytes<<qint64(this->outBlock.size()-sizeof(qint64)*2);
? ? //發(fā)送完文件頭結(jié)構(gòu)后剩余數(shù)據(jù)的大小
? ? this->bytesToWrite=this->totalBytes-this->tcpClient->write(this->outBlock);
?
? ? ui->label_state->setText(QString("已連接"));
? ? this->outBlock.resize(0);
}
?
void Client::updateClientProgress(qint64 numBytes)
{
? ? //更新已經(jīng)發(fā)送數(shù)據(jù)的大小
? ? this->bytesWritten+=(int)numBytes;
? ? //如果已經(jīng)發(fā)送了數(shù)據(jù)
? ? if(this->bytesToWrite>0)
? ? {
? ? ? ? //每次發(fā)送payloadSize大小的數(shù)據(jù),不足就發(fā)送剩余數(shù)據(jù)大小
? ? ? ? this->outBlock=this->localFile->read(qMin(this->bytesToWrite,this->payloadSize));
? ? ? ? //發(fā)送完一次數(shù)據(jù)后還剩余數(shù)據(jù)的大小
? ? ? ? this->bytesToWrite-=(int)this->tcpClient->write(this->outBlock);
? ? ? ? //清空發(fā)送緩沖區(qū)
? ? ? ? this->outBlock.resize(0);
? ? }
? ? else
? ? {
? ? ? ? //如果沒(méi)有發(fā)送任何數(shù)據(jù),就關(guān)閉文件
? ? ? ? this->localFile->close();
? ? }
?
? ? //更新進(jìn)度條
? ? ui->progressBar->setMaximum(this->totalBytes);
? ? ui->progressBar->setValue(this->bytesWritten);
?
? ? //發(fā)送完畢
? ? if(this->bytesWritten==this->totalBytes)
? ? {
? ? ? ? ui->label_state->setText(QString("傳送文件 %1 成功").arg(this->fileName));
? ? ? ? this->localFile->close(); //關(guān)閉文件
? ? ? ? this->tcpClient->close(); //關(guān)閉tcp連接
? ? }
}
?
void Client::displayError(QAbstractSocket::SocketError)
{
? ? qDebug()<<this->tcpClient->errorString()<<endl;
? ? this->tcpClient->close();
? ? ui->progressBar->reset();
? ? ui->label_state->setText(QString("客戶端已就緒!"));
? ? ui->pushButton_send->setEnabled(true);
}
?
void Client::on_pushButton_open_clicked()
{
? ? ui->progressBar->reset();
? ? ui->label_state->setText(QString("狀態(tài):等待文件打開(kāi)!"));
? ? this->openFile();
}
?
void Client::on_pushButton_send_clicked()
{
? ? this->send();
}
?
?
#include <QApplication>
#include "client.h"
#include <QTextCodec>
?
int main(int argc, char *argv[])
{
? ? QApplication a(argc, argv);
?
? ? QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
? ? QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
? ? QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
?
? ? Client w;
? ? w.show();
? ??
? ? return a.exec();
}服務(wù)器程序:
#ifndef SERVER_H
#define SERVER_H
?
#include <QDialog>
#include <QFile>
#include <QTcpSocket>
#include <QTcpServer>
#include <QAbstractSocket>
#include <QString>
#include <QByteArray>
?
namespace Ui {
class Server;
}
?
class Server : public QDialog
{
? ? Q_OBJECT
? ??
public:
? ? explicit Server(QWidget *parent = 0);
? ? ~Server();
?
private slots:
? ? void start();
? ? void acceptConnection();
? ? void updateServerProgress();
? ? void displayError(QAbstractSocket::SocketError socketError);
?
? ? void on_pushButton_clicked();
?
private:
? ? Ui::Server *ui;
?
? ? QTcpServer tcpServer; //服務(wù)器監(jiān)聽(tīng)
? ? QTcpSocket *tcpServerConnection; //來(lái)自客戶端的連接
?
? ? qint64 totalBytes; ?//存放總大小信息
? ? qint64 bytesReceived; //已收到的數(shù)據(jù)大小
? ? qint64 fileNameSize; //存放文件名的大小信息
?
? ? QString fileName; ?//存放文件名
? ? QFile *localFile; ?//本地文件
? ? QByteArray inBlock; ?//數(shù)據(jù)緩沖區(qū)
};
?
#endif // SERVER_H
?
#include "server.h"
#include "ui_server.h"
#include <QtNetwork>
#include <QDebug>
?
Server::Server(QWidget *parent) :
? ? QDialog(parent),
? ? ui(new Ui::Server)
{
? ? ui->setupUi(this);
? ? //有新的連接到來(lái),發(fā)射newConnection()信號(hào),獲取新的連接
? ? connect(&this->tcpServer,SIGNAL(newConnection()),this,SLOT(acceptConnection()));
}
?
Server::~Server()
{
? ? delete ui;
}
?
void Server::start()
{
? ? //建立監(jiān)聽(tīng)
? ? if(!this->tcpServer.listen(QHostAddress(QString("127.0.0.1")),6666))
? ? {
? ? ? ? qDebug()<<this->tcpServer.errorString()<<endl;
? ? ? ? close();
? ? ? ? return;
? ? }
?
? ? ui->pushButton->setEnabled(false);
? ? //初始化變量
? ? this->totalBytes=0;
? ? this->bytesReceived=0;
? ? this->fileNameSize=0;
?
? ? ui->label->setText(QString("監(jiān)聽(tīng)"));
? ? ui->progressBar->reset();
}
?
void Server::acceptConnection()
{
? ? //獲取來(lái)自客戶端的連接
? ? this->tcpServerConnection=this->tcpServer.nextPendingConnection();
? ? //建立信號(hào)連接
? ? connect(this->tcpServerConnection,SIGNAL(readyRead()),this,SLOT(updateServerProgress()));
? ? connect(this->tcpServerConnection,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
?
? ? ui->label->setText(QString("接收連接"));
?
? ? this->tcpServer.close();
}
?
void Server::updateServerProgress()
{
? ? QDataStream in(this->tcpServerConnection);
? ? in.setVersion(QDataStream::Qt_4_0);
? ? //如果接收到的數(shù)據(jù)小于16個(gè)字節(jié),保存到來(lái)的文件頭結(jié)構(gòu)
? ? if(this->bytesReceived<=sizeof(qint64)*2)
? ? {
? ? ? ? if((this->tcpServerConnection->bytesAvailable()>=sizeof(qint64)*2)&&(this->fileNameSize==0))
? ? ? ? {
? ? ? ? ? ? //接收數(shù)據(jù)總大小信息和文件名大小信息
? ? ? ? ? ? in>>this->totalBytes>>this->fileNameSize;
? ? ? ? ? ? this->bytesReceived+=sizeof(qint64)*2;
? ? ? ? }
?
? ? ? ? if((this->tcpServerConnection->bytesAvailable()>=this->fileNameSize)&&(this->fileNameSize!=0))
? ? ? ? {
? ? ? ? ? ? //接收文件名,并建立文件
? ? ? ? ? ? in>>this->fileName;
? ? ? ? ? ? ui->label->setText(QString("接收文件 %1 ......").arg(this->fileName));
? ? ? ? ? ? this->bytesReceived+=this->fileNameSize;
? ? ? ? ? ? this->localFile=new QFile(this->fileName);
? ? ? ? ? ? if(!this->localFile->open(QFile::WriteOnly))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? qDebug()<<"server: open file error"<<endl;
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? return;
? ? ? ? }
? ? }
? ? //開(kāi)始接收文件里面的數(shù)據(jù)
? ? if(this->bytesReceived<this->totalBytes)
? ? {
? ? ? ? this->bytesReceived+=this->tcpServerConnection->bytesAvailable();
? ? ? ? this->inBlock=this->tcpServerConnection->readAll();
? ? ? ? this->localFile->write(this->inBlock);
? ? ? ? this->inBlock.resize(0);
? ? ?}
?
? ? ui->progressBar->setMaximum(this->totalBytes);
? ? ui->progressBar->setValue(this->bytesReceived);
? ? //接收數(shù)據(jù)完成時(shí)
? ? if(this->bytesReceived==this->totalBytes)
? ? {
? ? ? ? this->tcpServerConnection->close();
? ? ? ? this->localFile->close();
? ? ? ? ui->pushButton->setEnabled(true);
? ? ? ? ui->label->setText(QString("接收文件 %1 成功").arg(this->fileName));
? ? }
}
?
void Server::displayError(QAbstractSocket::SocketError socketError)
{
? ? qDebug()<<this->tcpServerConnection->errorString();
? ? this->tcpServerConnection->close();
? ? ui->progressBar->reset();
? ? ui->label->setText(QString("服務(wù)端就緒"));
? ? ui->pushButton->setEnabled(true);
}
?
void Server::on_pushButton_clicked()
{
? ? start();
}
?
?
#include <QApplication>
#include "server.h"
#include <QTextCodec>
?
int main(int argc, char *argv[])
{
? ? QApplication a(argc, argv);
?
? ? QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
? ? QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
? ? QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
?
? ? Server w;
? ? w.show();
? ??
? ? return a.exec();
}
運(yùn)行結(jié)果:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Qt中TCP協(xié)議通信詳解
- QT實(shí)現(xiàn)簡(jiǎn)單TCP通信
- Qt實(shí)現(xiàn)簡(jiǎn)單的TCP通信
- QT編寫tcp通信工具(Client篇)
- QT網(wǎng)絡(luò)通信TCP客戶端實(shí)現(xiàn)詳解
- Qt網(wǎng)絡(luò)編程實(shí)現(xiàn)TCP通信
- QT5實(shí)現(xiàn)簡(jiǎn)單的TCP通信的實(shí)現(xiàn)
- 基于QT的TCP通信服務(wù)的實(shí)現(xiàn)
- QT網(wǎng)絡(luò)編程Tcp下C/S架構(gòu)的即時(shí)通信實(shí)例
- Qt TCP實(shí)現(xiàn)簡(jiǎn)單通信功能
相關(guān)文章
Visual Studio 2022 Preview 使用 C++20 Module的詳細(xì)過(guò)程
這篇文章主要介紹了Visual Studio 2022 Preview 使用 C++20 Module的過(guò)程,本文通過(guò)項(xiàng)目分析實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09
如何在C語(yǔ)言中判斷socket是否已經(jīng)斷開(kāi)
如果不主動(dòng)關(guān)閉socket的話,系統(tǒng)不會(huì)自動(dòng)關(guān)閉的,除非當(dāng)前進(jìn)程掛掉了,操作系統(tǒng)把占用的socket回收了才會(huì)關(guān)閉。小編今天跟大家簡(jiǎn)單介紹下如何在C語(yǔ)言中判斷socket是否已經(jīng)斷開(kāi)2019-05-05
C++利用jsoncpp庫(kù)實(shí)現(xiàn)寫入和讀取json文件
JsonCpp 是一個(gè)C++庫(kù),允許操作 JSON 值,包括序列化和反序列化到字符串和從字符串反序列化。本文主要介紹了如何利用jsoncpp庫(kù)實(shí)現(xiàn)寫入和讀取json文件,感興趣的可以了解一下2023-04-04
C++ for循環(huán)與nullptr的小知識(shí)點(diǎn)分享
這篇文章主要是來(lái)和大家介紹一些C++中的小知識(shí)點(diǎn),本文分享的是for循環(huán)與nullptr,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-05-05
opencv圖片的任意角度旋轉(zhuǎn)實(shí)現(xiàn)示例
這篇博客將介紹如何使用OpenCV旋轉(zhuǎn)圖像任意角度,實(shí)現(xiàn)各個(gè)角度的旋轉(zhuǎn),具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06

