赞
踩
qt下的QTcpSocket在同一个线程使用时没有问题的,但是如果进行跨线程,很容易出现问题。那么有什么方法可以跨线程进行使用吗?
答案是肯定的:使用QThread的movetothread可以完成扩线程接收。
首先是基于QTcpSocket的类 头文件tcpsocket.h
- #ifndef TCPSOCKET_H
- #define TCPSOCKET_H
- #include <QTcpSocket>
- #include <QHostAddress>
-
- class TcpSocket : public QTcpSocket
- {
- Q_OBJECT
- public:
- explicit TcpSocket( QObject *parent = NULL);
- explicit TcpSocket(int socketdesc, QObject *parent = NULL);
- ~TcpSocket();
- bool tcpConnect(const QString ip, const int port);
- signals:
- void socketSendData(const QString);
- public slots:
- bool start_connt(const QString IP, const int Port);
- void WriteToData(const QByteArray basend);
- void ReadAndParseData();
- void SocketErr(QAbstractSocket::SocketError socketError);
- void slotConnect();
- private:
- QString m_recvDataStr;
- };
-
- #endif // TCPSOCKET_H
然后是cpp文件tcpsocket.cpp
- #include "tcpsocket.h"
- #include <QDateTime>
-
-
- TcpSocket::TcpSocket(QObject *parent /*= NULL*/) : QTcpSocket(parent)
- {
-
-
- }
-
-
-
-
- TcpSocket::TcpSocket(int sock, QObject *parent) : QTcpSocket(parent)
- {
- this->setSocketDescriptor(sock);
- connect(this, SIGNAL(readyRead()), this, SLOT(ReadAndParseData()));
- connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(SocketErr(QAbstractSocket::SocketError)));
- connect(this, SIGNAL(connected()), this, SLOT(slotConnect()));
- connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
-
- }
-
-
-
- TcpSocket::~TcpSocket()
- {
-
-
- }
-
- bool TcpSocket::tcpConnect(const QString ip, const int port)
- {
-
- //this->abort();
- this->connectToHost(ip, port);
- bool recCon = this->waitForConnected(1000000);
- if (recCon)
- {
- connect(this, SIGNAL(readyRead()), this, SLOT(ReadAndParseData()));
- connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(SocketErr(QAbstractSocket::SocketError)));
- //connect(this, SIGNAL(connected()), this, SLOT(slotConnect()));
- //connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
- //write("Connect!!");
- }
- return recCon;
-
-
- }
-
- bool TcpSocket::start_connt(const QString IP, const int Port)
- {
-
-
- this->abort();
- this->connectToHost(IP, Port);
- this->waitForConnected();
- return true;
-
-
-
- }
- void TcpSocket::slotConnect()
- {
- qDebug() << "slotConnect";
-
- }
- // 将会移进线程里面运行
- void TcpSocket::ReadAndParseData()
- {
- int byteLen = 0;
- QString recvStr = "";
- //wait forreadyread()
- //if (this->waitForReadyRead(0))
- {
- byteLen = this->bytesAvailable();
-
- if (byteLen>0)
- {
-
- QByteArray readNet = this->readAll();
- recvStr = QString::fromLatin1(readNet);
- }
-
- }
-
- QDateTime tim = QDateTime::currentDateTime();
- QString curtime = tim.toString("yyyy:MM:dd:hh:mm:ss:zzz");
- qDebug() << curtime << " socket read data:" << recvStr;
-
- emit socketSendData(recvStr);
-
-
-
- }
-
- void TcpSocket::SocketErr(QAbstractSocket::SocketError socketError)
- {
- TcpSocket *socket = (TcpSocket*)sender();
- qDebug()<<"sock err= "<< socketError;
- }
-
- void TcpSocket::WriteToData(const QByteArray basend)
- {
-
-
- this->write(basend);
-
- }
-
-
再次基础上,创建tcpserver.h
- #ifndef TCPSERVER_H
- #define TCPSERVER_H
-
- #include <QTcpServer>
- #include <QThread>
- #include <QList>
- #include "tcpsocket.h"
- class TcpServer : public QTcpServer
- {
- Q_OBJECT
- public:
- explicit TcpServer( QObject *parent = NULL);
- ~TcpServer();
- void WriteToClient(const QByteArray strData );
- bool openServer(const QString IpAddress, const int PortNum);
- signals:
- void dataWrite( const QByteArray );
- void serverSend(const QString);
- protected:
- void incomingConnection(qintptr socketDescriptor);
- private slots:
- void disconnectSlot();
- void readDataSlot(const QString recdata);
- private:
- QList<TcpSocket*> m_socketList;
- };
-
-
-
-
- #endif // TCPSERVER_H
和 tcpserver.cpp
- #include "tcpserver.h"
- #include <QDateTime>
-
- TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
- {
-
- }
-
- TcpServer::~TcpServer()
- {
- /* QList<TcpSocket*>::iterator it = m_socketList.begin();
- for (; it != m_socketList.end(); )
- {
- TcpSocket* sock = *it;
- it = m_socketList.erase(it);
- sock->deleteLater();
- sock = NULL;
- }
- m_socketList.clear();*/
- this->close();
-
- }
-
- bool TcpServer::openServer(QString IpAddress, int PortNum)
- {
- bool bsucc;
- if (IpAddress.isEmpty())
- {
- bsucc = this->listen(QHostAddress::AnyIPv4, PortNum);
- }
- else
- {
-
- bsucc = this->listen(QHostAddress(IpAddress), PortNum);
- }
-
- return bsucc;
- }
-
- void TcpServer::incomingConnection(qintptr socketDescriptor)
- {
-
- TcpSocket *socket = new TcpSocket(socketDescriptor);
- m_socketList.append(socket);
- //外部调用信号连接
-
- connect(socket, SIGNAL(socketSendData(const QString)), this, SLOT(readDataSlot(const QString))); // 会移进线程里
-
-
- QThread *thread = new QThread();
- connect(socket, SIGNAL(disconnected()), thread, SLOT(quit()));//线程退出
- connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectSlot()));
- connect(this, SIGNAL(dataWrite(const QByteArray)), socket, SLOT(WriteToData(const QByteArray)));
-
- connect(thread,SIGNAL(finished()),socket,SLOT(deleteLater()));//删除socket
-
- socket->moveToThread(thread);
- thread->start();
- emit newConnection(); //文档要求继承本函数需要发射此信号,此处没有与此信号连接的槽
- }
-
- void TcpServer::disconnectSlot()
- {
- qDebug()<<"disconnect ok";
- }
-
- void TcpServer::readDataSlot(const QString recvStr)
- {
-
- QDateTime tim = QDateTime::currentDateTime();
- QString curtime = tim.toString("yyyy:MM:dd:hh:mm:ss:zzz");
- qDebug() << curtime << " server read data:" << recvStr;
-
- serverSend(recvStr);
-
-
- }
-
- void TcpServer::WriteToClient(const QByteArray strData )
- {
-
- emit dataWrite(strData);
-
- }
在调用的时候分为客户端和服务器两种
-
- if (m_cell->m_servSel<1) //客户端
- {
- m_tcp = new TcpSocket();
- bRet = m_tcp->tcpConnect(IpAddress, PortNum);
- if (bRet)
- {
- work_th = new QThread();
- // ui---线程 交互
-
- connect(this, SIGNAL(sig_send(const QByteArray)), m_tcp, SLOT(WriteToData(const QByteArray)));
- connect(m_tcp, SIGNAL(disconnected()), work_th, SLOT(quit()));//失去连接后线程退出
- //connect(m_tcp, SIGNAL(disconnected()), this, SLOT(disconnectSlot()));
-
- {
- connect(m_tcp, SIGNAL(socketSendData(const QString)), this, SLOT(rec_tcpClientData(const QString))); // 会移进线程里
- }
-
- connect(work_th, SIGNAL(finished()), m_tcp, SLOT(deleteLater()));//线程退出后删除socket
-
-
-
- m_tcp->moveToThread(work_th); //会移进线程里
- work_th->start();
-
-
- }
-
- }
- else //服务器 服务器的每一个客户端单独开线程,在此处不开。
- {
- m_server = new TcpServer();
- bRet = m_server->openServer(IpAddress, PortNum);
- if (bRet)
- {
-
-
- {
- connect(m_server, SIGNAL(serverSend(const QString)), this, SLOT(rec_tcpServerData(const QString)));
- }
-
- }
-
- }
这样就可以完成跨线程的收发了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。