当前位置:   article > 正文

QT下的多线程TCP客户端和服务器_qt tcp服务器

qt tcp服务器

qt下的QTcpSocket在同一个线程使用时没有问题的,但是如果进行跨线程,很容易出现问题。那么有什么方法可以跨线程进行使用吗?

答案是肯定的:使用QThread的movetothread可以完成扩线程接收。

首先是基于QTcpSocket的类 头文件tcpsocket.h

  1. #ifndef TCPSOCKET_H
  2. #define TCPSOCKET_H
  3. #include <QTcpSocket>
  4. #include <QHostAddress>
  5. class TcpSocket : public QTcpSocket
  6. {
  7. Q_OBJECT
  8. public:
  9. explicit TcpSocket( QObject *parent = NULL);
  10. explicit TcpSocket(int socketdesc, QObject *parent = NULL);
  11. ~TcpSocket();
  12. bool tcpConnect(const QString ip, const int port);
  13. signals:
  14. void socketSendData(const QString);
  15. public slots:
  16. bool start_connt(const QString IP, const int Port);
  17. void WriteToData(const QByteArray basend);
  18. void ReadAndParseData();
  19. void SocketErr(QAbstractSocket::SocketError socketError);
  20. void slotConnect();
  21. private:
  22. QString m_recvDataStr;
  23. };
  24. #endif // TCPSOCKET_H

然后是cpp文件tcpsocket.cpp

  1. #include "tcpsocket.h"
  2. #include <QDateTime>
  3. TcpSocket::TcpSocket(QObject *parent /*= NULL*/) : QTcpSocket(parent)
  4. {
  5. }
  6. TcpSocket::TcpSocket(int sock, QObject *parent) : QTcpSocket(parent)
  7. {
  8. this->setSocketDescriptor(sock);
  9. connect(this, SIGNAL(readyRead()), this, SLOT(ReadAndParseData()));
  10. connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(SocketErr(QAbstractSocket::SocketError)));
  11. connect(this, SIGNAL(connected()), this, SLOT(slotConnect()));
  12. connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
  13. }
  14. TcpSocket::~TcpSocket()
  15. {
  16. }
  17. bool TcpSocket::tcpConnect(const QString ip, const int port)
  18. {
  19. //this->abort();
  20. this->connectToHost(ip, port);
  21. bool recCon = this->waitForConnected(1000000);
  22. if (recCon)
  23. {
  24. connect(this, SIGNAL(readyRead()), this, SLOT(ReadAndParseData()));
  25. connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(SocketErr(QAbstractSocket::SocketError)));
  26. //connect(this, SIGNAL(connected()), this, SLOT(slotConnect()));
  27. //connect(this, SIGNAL(disconnected()), this, SLOT(deleteLater()));
  28. //write("Connect!!");
  29. }
  30. return recCon;
  31. }
  32. bool TcpSocket::start_connt(const QString IP, const int Port)
  33. {
  34. this->abort();
  35. this->connectToHost(IP, Port);
  36. this->waitForConnected();
  37. return true;
  38. }
  39. void TcpSocket::slotConnect()
  40. {
  41. qDebug() << "slotConnect";
  42. }
  43. // 将会移进线程里面运行
  44. void TcpSocket::ReadAndParseData()
  45. {
  46. int byteLen = 0;
  47. QString recvStr = "";
  48. //wait forreadyread()
  49. //if (this->waitForReadyRead(0))
  50. {
  51. byteLen = this->bytesAvailable();
  52. if (byteLen>0)
  53. {
  54. QByteArray readNet = this->readAll();
  55. recvStr = QString::fromLatin1(readNet);
  56. }
  57. }
  58. QDateTime tim = QDateTime::currentDateTime();
  59. QString curtime = tim.toString("yyyy:MM:dd:hh:mm:ss:zzz");
  60. qDebug() << curtime << " socket read data:" << recvStr;
  61. emit socketSendData(recvStr);
  62. }
  63. void TcpSocket::SocketErr(QAbstractSocket::SocketError socketError)
  64. {
  65. TcpSocket *socket = (TcpSocket*)sender();
  66. qDebug()<<"sock err= "<< socketError;
  67. }
  68. void TcpSocket::WriteToData(const QByteArray basend)
  69. {
  70. this->write(basend);
  71. }

再次基础上,创建tcpserver.h

  1. #ifndef TCPSERVER_H
  2. #define TCPSERVER_H
  3. #include <QTcpServer>
  4. #include <QThread>
  5. #include <QList>
  6. #include "tcpsocket.h"
  7. class TcpServer : public QTcpServer
  8. {
  9. Q_OBJECT
  10. public:
  11. explicit TcpServer( QObject *parent = NULL);
  12. ~TcpServer();
  13. void WriteToClient(const QByteArray strData );
  14. bool openServer(const QString IpAddress, const int PortNum);
  15. signals:
  16. void dataWrite( const QByteArray );
  17. void serverSend(const QString);
  18. protected:
  19. void incomingConnection(qintptr socketDescriptor);
  20. private slots:
  21. void disconnectSlot();
  22. void readDataSlot(const QString recdata);
  23. private:
  24. QList<TcpSocket*> m_socketList;
  25. };
  26. #endif // TCPSERVER_H

和 tcpserver.cpp

  1. #include "tcpserver.h"
  2. #include <QDateTime>
  3. TcpServer::TcpServer(QObject *parent) : QTcpServer(parent)
  4. {
  5. }
  6. TcpServer::~TcpServer()
  7. {
  8. /* QList<TcpSocket*>::iterator it = m_socketList.begin();
  9. for (; it != m_socketList.end(); )
  10. {
  11. TcpSocket* sock = *it;
  12. it = m_socketList.erase(it);
  13. sock->deleteLater();
  14. sock = NULL;
  15. }
  16. m_socketList.clear();*/
  17. this->close();
  18. }
  19. bool TcpServer::openServer(QString IpAddress, int PortNum)
  20. {
  21. bool bsucc;
  22. if (IpAddress.isEmpty())
  23. {
  24. bsucc = this->listen(QHostAddress::AnyIPv4, PortNum);
  25. }
  26. else
  27. {
  28. bsucc = this->listen(QHostAddress(IpAddress), PortNum);
  29. }
  30. return bsucc;
  31. }
  32. void TcpServer::incomingConnection(qintptr socketDescriptor)
  33. {
  34. TcpSocket *socket = new TcpSocket(socketDescriptor);
  35. m_socketList.append(socket);
  36. //外部调用信号连接
  37. connect(socket, SIGNAL(socketSendData(const QString)), this, SLOT(readDataSlot(const QString))); // 会移进线程里
  38. QThread *thread = new QThread();
  39. connect(socket, SIGNAL(disconnected()), thread, SLOT(quit()));//线程退出
  40. connect(socket, SIGNAL(disconnected()), this, SLOT(disconnectSlot()));
  41. connect(this, SIGNAL(dataWrite(const QByteArray)), socket, SLOT(WriteToData(const QByteArray)));
  42. connect(thread,SIGNAL(finished()),socket,SLOT(deleteLater()));//删除socket
  43. socket->moveToThread(thread);
  44. thread->start();
  45. emit newConnection(); //文档要求继承本函数需要发射此信号,此处没有与此信号连接的槽
  46. }
  47. void TcpServer::disconnectSlot()
  48. {
  49. qDebug()<<"disconnect ok";
  50. }
  51. void TcpServer::readDataSlot(const QString recvStr)
  52. {
  53. QDateTime tim = QDateTime::currentDateTime();
  54. QString curtime = tim.toString("yyyy:MM:dd:hh:mm:ss:zzz");
  55. qDebug() << curtime << " server read data:" << recvStr;
  56. serverSend(recvStr);
  57. }
  58. void TcpServer::WriteToClient(const QByteArray strData )
  59. {
  60. emit dataWrite(strData);
  61. }

在调用的时候分为客户端和服务器两种

  1. if (m_cell->m_servSel<1) //客户端
  2. {
  3. m_tcp = new TcpSocket();
  4. bRet = m_tcp->tcpConnect(IpAddress, PortNum);
  5. if (bRet)
  6. {
  7. work_th = new QThread();
  8. // ui---线程 交互
  9. connect(this, SIGNAL(sig_send(const QByteArray)), m_tcp, SLOT(WriteToData(const QByteArray)));
  10. connect(m_tcp, SIGNAL(disconnected()), work_th, SLOT(quit()));//失去连接后线程退出
  11. //connect(m_tcp, SIGNAL(disconnected()), this, SLOT(disconnectSlot()));
  12. {
  13. connect(m_tcp, SIGNAL(socketSendData(const QString)), this, SLOT(rec_tcpClientData(const QString))); // 会移进线程里
  14. }
  15. connect(work_th, SIGNAL(finished()), m_tcp, SLOT(deleteLater()));//线程退出后删除socket
  16. m_tcp->moveToThread(work_th); //会移进线程里
  17. work_th->start();
  18. }
  19. }
  20. else //服务器 服务器的每一个客户端单独开线程,在此处不开。
  21. {
  22. m_server = new TcpServer();
  23. bRet = m_server->openServer(IpAddress, PortNum);
  24. if (bRet)
  25. {
  26. {
  27. connect(m_server, SIGNAL(serverSend(const QString)), this, SLOT(rec_tcpServerData(const QString)));
  28. }
  29. }
  30. }

这样就可以完成跨线程的收发了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/187346
推荐阅读
相关标签
  

闽ICP备14008679号