2 Star 5 Fork 0

牛顶顶/TcpProtocolTest

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
tcpclient.cpp 7.59 KB
一键复制 编辑 原始数据 按行查看 历史
Ambition 提交于 2023-08-03 15:04 . update
#include "tcpclient.h"
#include <QDataStream>
TcpClient::TcpClient(QObject *parent) : QObject(parent)
{
}
void TcpClient::init()
{
m_socket = new QTcpSocket;
m_filesocket = new QTcpSocket;
m_payloadSize=64*1024;
m_recvtotalBytes=0;
m_recvbytesReceived=0;
m_recvfileNameSize=0;
connect(m_filesocket,SIGNAL(bytesWritten(qint64)),this,SLOT(updateClientProgress(qint64)));
connect(m_filesocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));
connect(m_filesocket,SIGNAL(readyRead()),this,SLOT(updateServerProgress()));
QObject::connect(m_socket,SIGNAL(connected()),this,SLOT(slotConnected()));
QObject::connect(m_socket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
QObject::connect(m_socket,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));
QObject::connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), this, &TcpClient::displayError);
}
void TcpClient::updateServerProgress(){
QDataStream in(m_filesocket);
in.setVersion(QDataStream::Qt_5_7);
// 如果接收到的数据小于16个字节,保存到来的文件头结构
if (m_recvbytesReceived<=sizeof(qint64)*2){
if((m_filesocket->bytesAvailable()>=sizeof(qint64)*2)&&(m_recvfileNameSize==0)){
// 接收数据总大小信息和文件名大小信息
in>>m_recvtotalBytes>>m_recvfileNameSize;
m_recvbytesReceived +=sizeof(qint64)*2;
}
if((m_filesocket->bytesAvailable()>=m_recvfileNameSize)&&(m_recvfileNameSize!=0)){
// 接收文件名,并建立文件
in>>m_recvfileName;
qDebug()<<tr("recv file %1").arg(m_recvfileName);
m_recvbytesReceived+=m_recvfileNameSize;
m_recvlocalFile = new QFile(m_recvfileName);
if (!m_recvlocalFile->open(QFile::WriteOnly)){
qDebug() << "server: open file error!";
return;
}
}
else{
return;
}
}
// 如果接收的数据小于总数据,那么写入文件
if(m_recvbytesReceived<m_recvtotalBytes) {
m_recvbytesReceived+=m_filesocket->bytesAvailable();
m_recvinBlock = m_filesocket->readAll();
m_recvlocalFile->write(m_recvinBlock);
m_recvinBlock.resize(0);
qDebug()<<tr("recv file %1").arg(m_recvfileName);
}
// 接收数据完成时
if (m_recvbytesReceived==m_recvtotalBytes){
//m_filesocket->close();
m_recvlocalFile->close();
m_recvtotalBytes=0;
m_recvbytesReceived=0;
m_recvfileNameSize=0;
qDebug()<<tr("recv file %1 sucess").arg(m_recvfileName);
}
}
void TcpClient::displayError(QAbstractSocket::SocketError){
qDebug()<<m_filesocket->errorString();
m_filesocket->close();
}
void TcpClient::clientConnectTo(QString ip, QString port)
{
m_socket->connectToHost(ip,port.toInt());
m_filesocket->connectToHost(ip,6666);
}
void TcpClient::sendData(const QString & data)
{
TcpProtocol tcpProtocol;
tcpProtocol.data = data.toUtf8().data();
QByteArray arr = tcpProtocol.getStream();
//for(int i =0 ;i <100 ;i++){
m_socket->write(arr);
m_socket->waitForBytesWritten();
//}
}
void TcpClient::closeConnect()
{
m_socket->close();
}
void TcpClient::slotReadyRead()
{
//缓冲区没有数据,直接无视
if( m_socket->bytesAvailable() <= 0 )
{
return;
}
//临时获得从缓存区取出来的数据,但是不确定每次取出来的是多少。
QByteArray buffer;
//如果是信号readyRead触发的,使用readAll时会一次把这一次可用的数据全总读取出来
//所以使用while(m_tcpClient->bytesAvailable())意义不大,其实只执行一次。
buffer = m_socket->readAll();
//上次缓存加上这次数据
m_buffer.append(buffer);
uint32_t size ;
int totalLen = m_buffer.size();
while( totalLen )
{
//与QDataStream绑定,方便操作。
QDataStream packet(m_buffer);
//不够包头的数据直接就不处理。
if( totalLen < OtherSize )
{
break;
}
packet >> size ;
//如果不够长度等够了在来解析
if( totalLen < size )
{
break;
}
TcpProtocol p(m_buffer);
if(p.cmd == 1){
signReadyRead(p);
}else if(p.cmd == 2){
save2File(p);
if(p.isLastPack != 1)
sendReadFileData(p);
}else if(p.cmd == 3){
if(p.seek >= m_file.size())
return;
sendFile(m_filePath,p.seek);
}else if(p.cmd == 4){
m_saveFileName = p.data;
sendReadFileData(p , -1);
}
//缓存多余的数据
buffer = m_buffer.right(totalLen - size);
//更新长度
totalLen = buffer.size();
if(buffer.size() != 0){
qDebug()<<"黏包";
}
//更新多余数据
m_buffer = buffer;
}
}
void TcpClient::slotConnected()
{
signConnected();
}
void TcpClient::slotDisconnected()
{
signDisconnected();
}
//void TcpClient::displayError(QAbstractSocket::SocketError err)
//{
// signDisplayError(err);
//}
void TcpClient::save2File(TcpProtocol tcpProtocol)
{
if(tcpProtocol.seek == 0){
m_file.close();
m_file.setFileName("./"+m_saveFileName);
m_file.open(QFile::WriteOnly);
}
m_file.seek(tcpProtocol.seek);
qDebug()<<"recive data seek = "<<tcpProtocol.seek<<"tcpProtocol.data.size() + tcpProtocol.seek"<<tcpProtocol.data.size()+tcpProtocol.seek;
m_file.write(tcpProtocol.data.data(),tcpProtocol.data.size());
if(tcpProtocol.isLastPack == 1){
m_file.close();
qDebug()<<"file save sucess";
}
}
void TcpClient::sendReadFileData(TcpProtocol tcpProtocol, int num)
{
TcpProtocol sendtcpProtocol;
sendtcpProtocol.cmd = 3;
if(num == -1){
sendtcpProtocol.seek = 0;
}else{
sendtcpProtocol.seek = tcpProtocol.seek + tcpProtocol.data.size();
qDebug()<<"tcpProtocol.data.size() = "<<tcpProtocol.data.size();
qDebug()<<"tcpProtocol.seek = "<<tcpProtocol.seek;
}
QByteArray arr = sendtcpProtocol.getStream();
m_socket->write(arr);
m_socket->waitForBytesWritten();
}
void TcpClient::sendFile(const QString &filepath, int seek)
{
m_fileName = filepath;
startTransfer();
}
void TcpClient::startTransfer()
{
m_localFile=new QFile(m_fileName);
if(!m_localFile->open(QFile::ReadOnly)){
qDebug()<<"client:open file error!";
return;
}
m_totalBytes=m_localFile->size();
QDataStream sendOut(&m_outBlock,QIODevice::WriteOnly);
sendOut.setVersion(QDataStream::Qt_5_7);
QString currentFileName=m_fileName.right(m_fileName.size()-m_fileName.lastIndexOf('/')-1);
//文件总大小、文件名大小、文件名
sendOut<<qint64(0)<<qint64(0)<<currentFileName;
m_totalBytes+=m_outBlock.size();
sendOut.device()->seek(0);
sendOut<<m_totalBytes<<qint64(m_outBlock.size()-sizeof(qint64)*2);
m_bytesToWrite=m_totalBytes-m_filesocket->write(m_outBlock);
m_outBlock.resize(0);
}
void TcpClient::updateClientProgress(qint64 numBytes)
{
m_bytesWritten+=(int)numBytes;
if(m_bytesToWrite>0){
m_outBlock=m_localFile->read(qMin(m_bytesToWrite,m_payloadSize));
m_bytesToWrite-=(int)m_filesocket->write(m_outBlock);
m_outBlock.resize(0);
qDebug()<<__FUNCTION__<<"numBytes = "<<numBytes;
}else{
m_localFile->close();
}
if(m_bytesWritten==m_totalBytes){
m_localFile->close();
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/shijingying/TcpProtocolTest.git
git@gitee.com:shijingying/TcpProtocolTest.git
shijingying
TcpProtocolTest
TcpProtocolTest
master

搜索帮助