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);
}
在调用的时候分为客户端和服务器两种文章来源:https://www.toymoban.com/news/detail-796719.html
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)));
}
}
}
这样就可以完成跨线程的收发了。文章来源地址https://www.toymoban.com/news/detail-796719.html
到了这里,关于QT下的多线程TCP客户端和服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!