使用Qt的qtcpsocket和qtcpserver类构建一个文件传输的服务端和客户端,客户端请求一个文件,服务器想客户端发送文件,可是客户端总是无法接收全部的包,比如把一个文件切分成1500个包,客户端每次只能接收1300个左右。
直接使用原始的socket编写的话,是没有任何问题,大文件传输也正常
但是Qt就不行,我做过测试,如果每次发送后,客户端回应服务器的话,就没有问题,可以接收全部。没有回应,一直接收的话,就会造成最后的一部分包无法不能接收,不知道是什么原因,可能是因为服务器没有发出。
测试如下,真不知道错在哪里
- C/C++ code
客户端:// main.cpp#include <QtCore/QCoreApplication>#include "transfer_clt.h"int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); transfer_clt clt; return a.exec();}// transfer_clt.h#ifndef TRANSFER_CLT_H#define TRANSFER_CLT_H#include <QObject>#include <QtCore>#include <QtNetwork>#include <QFile>#define DOWN_GET_FILE 10#define DOWN_TRANSFER 11#define DOWN_OVER 12class transfer_clt : public QObject{ Q_OBJECTpublic: explicit transfer_clt(QObject *parent = 0); signals: public slots: void on_connected(); void on_readyRead(); void on_error(QAbstractSocket::SocketError socketError);private: QTcpSocket *tcpSocket; int count; QFile *file;};#endif // TRANSFER_CLT_H// transfer_clt.cpp#include "transfer_clt.h"transfer_clt::transfer_clt(QObject *parent) : QObject(parent){ tcpSocket = new QTcpSocket; count = 0; connect(tcpSocket, SIGNAL(connected()), this, SLOT(on_connected())); connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(on_readyRead())); connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(on_error(QAbstractSocket::SocketError))); tcpSocket->connectToHost("127.0.0.1", 9100);}void transfer_clt::on_connected (){ qDebug () << "require file"; QString fileName = "Sweety.txt"; // 请求的文件 file = new QFile(fileName); if (!file->open(QFile::WriteOnly )) { qDebug () << tr("cannot open file"); return; } QByteArray outBlock; QDataStream out(&outBlock, QIODevice::WriteOnly); out << DOWN_GET_FILE << fileName; tcpSocket->write(outBlock);}void transfer_clt::on_error (QAbstractSocket::SocketError){ qDebug() << "on_error() : " << tcpSocket->errorString(); tcpSocket->close ();}void transfer_clt::on_readyRead(){ int type; QDataStream in (tcpSocket); QByteArray inBlock; tcpSocket->bytesAvailable(); in >> type; if(type == DOWN_TRANSFER) { in >> inBlock; file->write(inBlock); qDebug() << "count = " << count++ << " size: " << inBlock.size(); } else if (type == DOWN_OVER) { qDebug() << "end" ; file->close (); tcpSocket->close (); }}// 服务端://main.cpp#include <QtCore/QCoreApplication>#include "transfer_srv.h"int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); transfer_srv srv; return a.exec();}// transfer_srv.h#ifndef TRANSFER_SRV_H#define TRANSFER_SRV_H#include <QObject>#include <QtCore>#include <QtNetwork>#include <QFile>#define DOWN_GET_FILE 10#define DOWN_TRANSFER 11#define DOWN_OVER 12class transfer_srv : public QObject{ Q_OBJECTpublic: explicit transfer_srv(QObject *parent = 0); signals: public slots: void on_newConnection(); void on_readyRead(); void on_bytesWritten(qint64 numBytes); void on_error(QAbstractSocket::SocketError socketError);private: QTcpSocket *tcpSocket; QTcpServer tcpServer; int count; QFile *file; qint64 byteToWrite; };#endif // TRANSFER_SRV_H// transfer_srv.cpp#include "transfer_srv.h"qint64 blockSize = 4*1024;transfer_srv::transfer_srv(QObject *parent) : QObject(parent){ count = 0; while (!tcpServer.isListening() && !tcpServer.listen(QHostAddress::LocalHost, 9100)) { qDebug() << "Server cannot listen on port " << 9100; return; } connect(&tcpServer, SIGNAL(newConnection()), this, SLOT(on_newConnection())); qDebug() << "start service...";}void transfer_srv::on_newConnection (){ tcpSocket = tcpServer.nextPendingConnection(); qDebug() << "connection to : " << tcpSocket; connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(on_readyRead())); connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(on_error(QAbstractSocket::SocketError))); connect(tcpSocket, SIGNAL(bytesWritten(qint64)), this, SLOT(on_bytesWritten(qint64))); }void transfer_srv::on_error (QAbstractSocket::SocketError){ qDebug() << "on_error() : " << tcpSocket->errorString(); tcpSocket->close (); count = 0;}void transfer_srv::on_readyRead(){ int type; QDataStream in (tcpSocket); in >> type; if(type == DOWN_GET_FILE) { QString fileName; in >> fileName; qDebug () << "require file : " << fileName; file = new QFile(fileName); if (!file->open(QFile::ReadOnly )) { qDebug () << tr("cannot open file"); return; } byteToWrite = file->size(); QByteArray tmp; tmp = file->read(qMin(blockSize, byteToWrite)); byteToWrite -= qMin(blockSize, byteToWrite); QByteArray outBlock; QDataStream out(&outBlock, QIODevice::WriteOnly); out << DOWN_TRANSFER << tmp; int num = tcpSocket->write (outBlock); qDebug () << "count = " << count ++ << "size: " << num ; }}void transfer_srv::on_bytesWritten(qint64 numBytes){ static bool status = true; if(status == false) return; QByteArray outBlock; QDataStream out(&outBlock, QIODevice::WriteOnly); if(byteToWrite > 0) { QByteArray tmp; tmp = file->read(qMin(blockSize, byteToWrite)); byteToWrite -= qMin(blockSize, byteToWrite); out << DOWN_TRANSFER << tmp; tcpSocket->write (outBlock); qDebug () << "count = " << count ++ << "size: " << outBlock.size(); } else { tcpSocket->flush(); qDebug() << "end" ; out << DOWN_OVER ; file->close (); tcpSocket->write (outBlock); tcpSocket->flush(); status = false; }}