#include "tcpthread.h" #include <QtGui> #include <QtNetwork> #include <protocal.h> #include <QApplication> #include <QTcpSocket> #include <QTextCodec> #include <socket.h> int TcpThread::time = 0; int TcpThread::time2 = 0; //构造函数完成简单的赋值/ //TcpThread::TcpThread(int socketDescriptor, QObject *parent): //QThread(parent),socketDescriptor(socketDescriptor) //{ //} TcpThread::TcpThread(QObject *parent) { tcpSocket = new QTcpSocket; connect(tcpSocket,SIGNAL(readyRead()), this,SLOT(readyToRead())); } TcpThread::~TcpThread() { this->tcpSocket->deleteLater(); quit(); wait(); } //因为QT的线程的执行都是从run()开始, //所以在此函数里完成tcpsocket的创建,相关信号的绑定 void TcpThread::run() { qDebug()<<"fefff"; tcpSocket->connectToHost("127.0.0.1",12580); bytesReceived = 0; threadprotocal = new Protocal; threadparsejson = new ParseJson(); qDebug()<<socketDescriptor; //这是重中之重,必须加Qt::BlockingQueuedConnection! //这里困扰了我好几天,原因就在与开始没加,默认用的Qt::AutoConnection。 //简单介绍一下QT信号与槽的连接方式: //Qt::AutoConnection表示系统自动选择相应的连接方式,如果信号与槽在同一线程,就采用Qt::DirectConnection,如果信号与槽不在同一线程,将采用Qt::QueuedConnection的连接方式。 //Qt::DirectConnection表示一旦信号产生,立即执行槽函数。 //Qt::QueuedConnection表示信号产生后,将发送Event给你的receiver所在的线程,postEvent(QEvent::MetaCall,...),slot函数会在receiver所在的线程的event loop中进行处理。 //Qt::BlockingQueuedConnection表示信号产生后调用sendEvent(QEvent::MetaCall,...),在receiver所在的线程处理完成后才会返回;只能当sender,receiver不在同一线程时才可以。 //Qt::UniqueConnection表示只有它不是一个重复连接,连接才会成功。如果之前已经有了一个链接(相同的信号连接到同一对象的同一个槽上),那么连接将会失败并将返回false。 //Qt::AutoCompatConnection与QT3保持兼容性 //说明一下,对于任何的QThread来说,其线程只存在于run()函数内,其它的函数都不在线程内,所以此处要采用Qt::BlockingQueuedConnection, //因为当SOCKET有数据到达时就会发出readyRead()信号,但是此时可能之前的receiveFile()还未执行完毕,之前使用的Qt::AutoConnection, //结果传输大文件的时候就会出错,原因就在于只要有数据到达的时候,就会连接信号,但是数据接收还没处理完毕,而Qt::BlockingQueuedConnection会阻塞 //此连接,直到receiveFile()处理完毕并返回后才发送信号。 // connect(tcpSocket, SIGNAL(readyRead()), // this, SLOT(receiveFile()),Qt::BlockingQueuedConnection); //定时器定时发送判断服务器是否连接 timer = new QTimer; timer->setInterval(5000); timer->start(); connect(timer,SIGNAL(timeout()),this,SLOT(timedone()),Qt::DirectConnection); connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); connect(this,SIGNAL(sendIfConnect(int,quint16,int,QString)),this,SLOT(slotsendInfo(int,quint16,int,QString))); connect(tcpSocket,SIGNAL(readyRead()), this,SLOT(readyToRead())); connect(this,SIGNAL(singalJson(QByteArray)),threadparsejson,SLOT(parseJsonSlot(QByteArray))); //initAllConnect(); exec(); qDebug()<<"timer start"; } void TcpThread::timedone() { qDebug()<<"emit timeimit"; time = 0; emit sendIfConnect(10,MSG_OPERATE_CMD_NONE,0,NULL); qDebug()<<"emit 123"; } bool TcpThread::linkServer() { qDebug()<<"Link....."; initAllConnect(); qDebug()<<"234+++"; //tcpSocket->abort(); //tcpSocket->connectToHost("127.0.0.1",12580); qDebug()<<12345; if(!tcpSocket->waitForConnected(50000)) { qDebug()<<"Connected Error"; return false; }else { return true; } } void TcpThread::breakServer() { tcpSocket->close(); } void TcpThread::initAllConnect(void) { connect(tcpSocket,SIGNAL(readyRead()), this,SLOT(readyToRead())); qDebug()<<9876; } void TcpThread::readyToRead() { //qDebug()<<"read msg"; reviceIfConnection(); //receiveFile(); } void TcpThread::slotsendInfo(int useroperate,quint16 operatecmd,int datasize,QString datadetail) { // if(this->linkServer()) // { // qDebug()<<"Link Server"; QString msg; msg.append(QString::number(10)).append(MSG_DATA_ITEMS_SEPARATOR).append(MSG_OPERATE_CMD_NONE); qDebug()<<msg<<"++++==="; sendCheckConn(10,MSG_OPERATE_CMD_NONE,msg.size(),msg); qDebug()<<"12345 link scussful"; // }else // { // qDebug()<<"Server Conn Filed"; // } } void TcpThread::sendCheckConn(int useroperate,quint16 operatecmd, int datasize,QString datadetail) { QString send = threadprotocal->updataMsg( useroperate,operatecmd, datasize, datadetail); qDebug()<<threadprotocal->getDataDetail(); qDebug()<<threadprotocal->getDataSize(); QTextCodec *utf8 = QTextCodec::codecForName("UTF-8"); QString SendMsg = utf8->toUnicode(send.toUtf8()); // gbk convert utf8 qDebug()<<SendMsg; tcpSocket->write(SendMsg.toStdString().c_str(),strlen(SendMsg.toStdString().c_str())); //发送 qDebug()<<"send infomation scussfull"; } void TcpThread::reviceIfConnection() { //qDebug()<<6668888; tcpSocket->setSocketOption( QAbstractSocket::ReceiveBufferSizeSocketOption, 1024*1024*1024); tcpSocket->setReadBufferSize(1024*1024*1024); //int MAX_BUFFER_SIZE = 1024*100; QByteArray MsgSize; QByteArray RecMsg; int ReciveSize; if(time == 0) { MsgSize = tcpSocket->read(10); QString msg = MsgSize.data(); ReciveSize = msg.toInt(); qDebug()<<msg<<""<<ReciveSize<<"++++接收长度+++++"; if(ReciveSize == 0) { return; } time = time + 1; } if(tcpSocket->bytesAvailable()< ReciveSize) //如果数据没有接收完全,则继续接收数据 { return; } RecMsg = tcpSocket->read(ReciveSize); time= 0; QString msg = RecMsg.data(); qDebug()<<msg<<"-----"; singalJson(RecMsg); RecMsg = ""; } void TcpThread::receiveFile() { //将tcpsocket封装到QDataStream里,便于使用操作符>> QDataStream in(tcpSocket); if(bytesReceived < sizeof(qint32)) { //先接收32bit的文件大小 if(tcpSocket->bytesAvailable() >= sizeof(qint32)) { in.setByteOrder(QDataStream::LittleEndian); //必须的,因为发送端为LINUX系统 in>>TotalBytes; TotalBytes += 4; qDebug()<<TotalBytes; bytesReceived += sizeof(qint32); fileName = tcpSocket->peerAddress(); quint16 port = tcpSocket->peerPort(); localFile = new QFile(fileName.toString()+(tr(".%1").arg(port))); //用户端的IP地址作为保存文件名 if(!localFile->open(QFile::WriteOnly )) { } } } //如果读取的文件小于文件大小就继续读 if (bytesReceived < TotalBytes){ byteToRead = tcpSocket->bytesAvailable(); bytesReceived += byteToRead; inBlock = tcpSocket->readAll(); qDebug()<<"bytesReceived is:"<<bytesReceived; localFile->write(inBlock); inBlock.resize(0); } emit bytesArrived(bytesReceived,TotalBytes,socketDescriptor); if (bytesReceived == TotalBytes) { localFile->close(); qDebug()<<bytesReceived; //emit finished(); QApplication::restoreOverrideCursor(); } }