qt下的QTcpSocket在同一個線程使用時沒有問題的,但是如果進行跨線程,很容易出現(xiàn)問題。那么有什么方法可以跨線程進行使用嗎?
答案是肯定的:使用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);
}
再次基礎(chǔ)上,創(chuàng)建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);
//外部調(diào)用信號連接
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(); //文檔要求繼承本函數(shù)需要發(fā)射此信號,此處沒有與此信號連接的槽
}
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);
}
在調(diào)用的時候分為客戶端和服務(wù)器兩種文章來源:http://www.zghlxwxcb.cn/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 //服務(wù)器 服務(wù)器的每一個客戶端單獨開線程,在此處不開。
{
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)));
}
}
}
這樣就可以完成跨線程的收發(fā)了。文章來源地址http://www.zghlxwxcb.cn/news/detail-796719.html
到了這里,關(guān)于QT下的多線程TCP客戶端和服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!