Qt?TCP網(wǎng)絡(luò)通信學(xué)習(xí)
TCP簡介:
Transmission Control Protocol,傳輸控制協(xié)議 。用于數(shù)據(jù)傳輸?shù)牡蛯泳W(wǎng)絡(luò)協(xié)議,多個物聯(lián)網(wǎng)協(xié)議都是基于TCP協(xié)議的。它是一個面向數(shù)據(jù)流和連接的可靠傳輸協(xié)議。
TCP頭部格式:
QTcpSocket類為TCP提供了一個接口,繼承自QAbstractSocket??蓪崿F(xiàn)POP3、SMTP、NNTP等標(biāo)準(zhǔn)的網(wǎng)絡(luò)協(xié)議,也可以實現(xiàn)自定義的網(wǎng)絡(luò)協(xié)議。異步工作,依靠事件循環(huán)來檢測到來的數(shù)據(jù),并且自動刷新輸出的數(shù)據(jù)。而QAbstractSocket繼承自QIODevice,故該類具備文件的讀寫功能,可以使用QTextStream和QDataStream。
QHostAddress QAbstractSocket::peerAddress () const 獲取主機(jī)的IP地址
quint16 QAbstractSocket::peerPort () const 獲取主機(jī)的端口號
qint64 QIODevice::write ( const QByteArray & byteArray ) //寫入數(shù)據(jù),即通過TCP發(fā)送數(shù)據(jù)。
QByteArray QIODevice::read ( qint64 maxSize ) //讀取數(shù)據(jù),最多讀取maxSize。即獲取TCP接收的存放在緩沖區(qū)的數(shù)據(jù)
QByteArray QIODevice::readAll () //獲取TCP存放在緩沖區(qū)可讀取的所有數(shù)據(jù)。
從一個QTcpSocket中讀取數(shù)據(jù)前,必須先調(diào)用qint64 QIODevice::bytesAvailable () const 函數(shù)來確保已經(jīng)有足夠的數(shù)據(jù)可用。
涉及到的信號:
void QAbstractSocket::connected () [signal] 當(dāng)連接建立成功發(fā)射連接信號,指示一個已建立的新連接。
void QAbstractSocket::error ( QAbstractSocket::SocketError socketError ) [signal] 連接發(fā)生了錯誤,就會發(fā)送error()信號,參數(shù)指示發(fā)生了什么錯誤。
void QAbstractSocket::disconnected () [signal] 斷開一個已經(jīng)存在的連接時,發(fā)射斷開信號。
void QAbstractSocket::stateChanged ( QAbstractSocket::SocketState socketState ) [signal] 狀態(tài)改變都會發(fā)射stateChanged()信號。
void QIODevice::bytesWritten ( qint64 bytes ) [signal] 表示數(shù)據(jù)寫入完成,對應(yīng)的可以調(diào)用bytesToWrite()方法了解寫入了多少字節(jié)的數(shù)據(jù)。
void QIODevice::readyRead () [signal] 表示有數(shù)據(jù)可以讀取,對應(yīng)的可以調(diào)用bytesAvailable()方法了解可以讀取多少字節(jié)的數(shù)據(jù)。
一個簡單的TCP客戶端和服務(wù)端程序,單連接。
客戶端程序:
#ifndef QTTCPCLIENT_H #define QTTCPCLIENT_H ? #include <QObject> #include <QAbstractSocket> ? class QTcpSocket; //前置聲明 ? //客戶端程序 ?單連接,即一個客戶端一個服務(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ā)生的錯誤 ? ? 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); ? ? //建立信號連接,readyRead表示有數(shù)據(jù)過來,需要讀取 ? ? connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessage())); ? ? //建立信號連接,error(QAbstractSocket::SocketError)連接發(fā)生錯誤或關(guān)閉時會發(fā)射此信號 ? ? 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ù)的開頭 ? ? out<<(quint16)(block.size()-sizeof(quint16)); //添加數(shù)據(jù)大小信息到數(shù)據(jù)開頭 ? ? ? 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; ? ? } ? ? //如果沒有接收完全部數(shù)據(jù),則返回繼續(xù)接收 ? ? if(tcpSocket->bytesAvailable()<blockSize) ? ? { ? ? ? ? return; ? ? } ? ? //將接收的數(shù)據(jù)存放到變量中 ? ? in>>message; ? ? ? qDebug()<<message; ? ? ? this->sendMessage(); ? ? ? //斷開連接 ? ? tcpSocket->disconnectFromHost(); } ? void QtTcpClient::displayError(QAbstractSocket::SocketError) { ? ? switch(tcpSocket->error()) ? ? { ? ? case QAbstractSocket::RemoteHostClosedError: ?//遠(yuǎn)程服務(wù)端關(guān)閉連接錯誤 ? ? ? ? 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ù)端程序 ?單連接,即一個客戶端一個服務(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ā)生的錯誤 ? private: ? ? QTcpServer *tcpServer; //tcp服務(wù)端 ? ? ? QTcpSocket *clientConnect;//來自客戶端的連接 ? ? 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); ? ? ? //開始監(jiān)聽 ? ? if(!tcpServer->listen(QHostAddress(QString("127.0.0.1")),6666)) ? ? { ? ? ? ? qDebug()<<tcpServer->serverError()<<endl; ? ? ? ? qDebug()<<tcpServer->errorString()<<endl; ? ? ? ? qApp->exit(); ? ? } ? ? //建立信號連接,每來一個新的連接,就發(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)連接斷開時刪除該套接字 ? ? 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ù)會一直等待套接字將所有數(shù)據(jù)發(fā)送完畢,然后關(guān)閉該套接字,并發(fā)射disconnected信號 ? ? ? ? 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(); }
運行結(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ù)器成功時,發(fā)送connected()信號,開始傳送文件 ? ? connect(this->tcpClient,SIGNAL(connected()),this,SLOT(startTransfer())); ? ? //每次發(fā)送成功后發(fā)送bytesWritten(qint64))信號,告訴已成功發(fā)送的數(shù)據(jù)塊大小,并更新進(jìn)度條 ? ? connect(this->tcpClient,SIGNAL(bytesWritten(qint64)),this,SLOT(updateClientProgress(qint64))); ? ? //接收tcp連接發(fā)生的錯誤 ? ? 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("打開文件 %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); ? ? //打開文件 ? ? if(!this->localFile->open(QFile::ReadOnly)) ? ? { ? ? ? ? qDebug()<<"client: open file error!"<<endl; ? ? ? ? return; ? ? } ? ? ? //獲取打開文件的大小 ? ? 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; ? ? //總大小變量為總大小信息、文件名大小信息、文件名和實際文件大小的總和 ? ? this->totalBytes+=this->outBlock.size(); ? ? //返回outBlock的開始,填入總大小信息 ? ? sendOut.device()->seek(0); ? ? //填入各個項的大小信息以及文件名 ? ? 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 ? ? { ? ? ? ? //如果沒有發(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):等待文件打開!")); ? ? 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)聽 ? ? QTcpSocket *tcpServerConnection; //來自客戶端的連接 ? ? ? 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); ? ? //有新的連接到來,發(fā)射newConnection()信號,獲取新的連接 ? ? connect(&this->tcpServer,SIGNAL(newConnection()),this,SLOT(acceptConnection())); } ? Server::~Server() { ? ? delete ui; } ? void Server::start() { ? ? //建立監(jiān)聽 ? ? 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)聽")); ? ? ui->progressBar->reset(); } ? void Server::acceptConnection() { ? ? //獲取來自客戶端的連接 ? ? this->tcpServerConnection=this->tcpServer.nextPendingConnection(); ? ? //建立信號連接 ? ? 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個字節(jié),保存到來的文件頭結(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; ? ? ? ? } ? ? } ? ? //開始接收文件里面的數(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ù)完成時 ? ? 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(); }
運行結(jié)果:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++中STL的優(yōu)先隊列priority_queue詳解
這篇文章主要介紹了C++中STL的優(yōu)先隊列priority_queue詳解,今天講一講優(yōu)先隊列(priority_queue),實際上,它的本質(zhì)就是一個heap,我從STL中扒出了它的實現(xiàn)代碼,需要的朋友可以參考下2023-08-08