当前位置:   article > 正文

QT QTcpServer多线程服务器_qt tcpserver多线程

qt tcpserver多线程

客户端程序

1. 在.pro工程文件中,加入qt 网络支持

  1. QT += core gui \
  2. network

2.创建 ClientSocket 类

客户端的主要功能包括:

连接服务器,断开服务器,接收并显示服务器数据,向服务器发送数据

  1. //.h
  2. class ClientSocket : public QTcpSocket
  3. {
  4. Q_OBJECT
  5. public:
  6. explicit ClientSocket(QObject *parent = Q_NULLPTR);
  7. ~ClientSocket();
  8. bool CilentConect(QHostAddress hadd,ushort port);//连接服务器
  9. void CilentBreakConect();//断开服务器
  10. void TransMess(QString str);//向服务器发送数据
  11. signals:
  12. void dataReady(const QString &ip, const QByteArray &data);//从服务器接收到数据后向界面层发送信号
  13. private slots:
  14. void recvData();//对QTcpSocket 接收到数据产生的信号设定的槽函数
  15. };
  16. //.cpp
  17. ClientSocket::ClientSocket(QObject *parent) :QTcpSocket(parent)
  18. {
  19. connect(this,SIGNAL(readyRead()),this,SLOT(recvData()));//底层信号readyRead -> 槽函数recvDate
  20. }
  21. ClientSocket::~ClientSocket()
  22. {
  23. }
  24. bool ClientSocket::CilentConect(QHostAddress hadd,ushort port)
  25. {
  26. this->connectToHost(hadd,port);
  27. if (this->waitForConnected(1000)) // 连接成功则true
  28. {
  29. return true;
  30. }
  31. return false;
  32. }
  33. void ClientSocket::CilentBreakConect()
  34. {
  35. this->disconnectFromHost();//断开连接
  36. }
  37. void ClientSocket:: TransMess(QString str)//发送数据
  38. {
  39. this->write(str.toLocal8Bit());
  40. }
  41. void ClientSocket:: recvData() //从服务器接收到数据后
  42. {
  43. QString ip = peerAddress().toString().remove(0, 7);
  44. QByteArray data = readAll();
  45. emit dataReady(ip, data); //向界面层发送带数据的信号量
  46. }

3.客户端以及ui设计

  1. //.h
  2. class Widget : public QWidget
  3. {
  4. Q_OBJECT
  5. public:
  6. explicit Widget(QWidget *parent = 0);
  7. ~Widget();
  8. private slots:
  9. void on_pushButton_Connect_clicked();//连接与断开服务器槽函数
  10. void on_pushButtonTrans_clicked();//发送数据槽函数
  11. void recvData(const QString &ip, const QByteArray &data);//接收数据处理槽函数
  12. private:
  13. Ui::Widget *ui;
  14. ClientSocket *Cilent;//客户端Socket类
  15. };
  16. //.cpp
  17. Widget::Widget(QWidget *parent) :
  18. QWidget(parent),
  19. ui(new Ui::Widget)
  20. {
  21. ui->setupUi(this);
  22. Cilent = new ClientSocket(parent);
  23. //客户端类接收到数据的信号连接到界面处理函数
  24. connect(Cilent, SIGNAL(dataReady(const QString&, const QByteArray&)),this, SLOT(recvData(const QString&, const QByteArray&)));
  25. }

服务器端程序

服务器端程序的主要思路是,创建一个  QTcpServer 来侦听某一个端口,当有客户端接入时,启动一个线程,并创建一个Socket与对应的客户端通讯。所以这里涉及到四个部分:界面类,服务器类,通讯线程处理和服务器Socket。

服务器端及UI设计

 

  1. //.h
  2. class Widget : public QWidget
  3. {
  4. Q_OBJECT
  5. public:
  6. explicit Widget(QWidget *parent = 0);
  7. ~Widget();
  8. public:
  9. void showNewConnection(int sockDesc);//提示新连接 sockDesc:客户端ID
  10. void showDisconnection(int sockDesc);//提示连接断开
  11. signals:
  12. void MessOk(const QString &mess);
  13. private slots:
  14. void MessWindUpdate(const QString &mess);
  15. void on_pushButton_Trans_clicked(); //发送数据按键响应槽函数
  16. void on_pushButton_StartServer_clicked();//启动或关闭服务器槽函数
  17. signals:
  18. void sendData(int id, const QByteArray &data); //发送数据产生信号
  19. public slots:
  20. void recvData(const QString &ip, const QByteArray &data);//接收到数据后的处理槽函数
  21. private:
  22. Ui::Widget *ui;
  23. Server *m_Server;
  24. };
  25. //.c
  26. void Widget::on_pushButton_StartServer_clicked()
  27. {
  28. QHostAddress address;
  29. if(ui->pushButton_StartServer->text() == "启动服务器")
  30. {
  31. QString localHostName = QHostInfo::localHostName(); //获取主机名
  32. ui->textBrowser_ServerMess->insertPlainText(localHostName+'\n');
  33. QHostInfo info = QHostInfo::fromName(localHostName); //获取主机IP
  34. foreach(address,info.addresses())//获取IPV4的第一个ip
  35. {
  36. if(address.protocol() == QAbstractSocket::IPv4Protocol)
  37. {
  38. ui->textBrowser_ServerMess->insertPlainText(address.toString()+'\n');
  39. break;
  40. }
  41. }
  42. QString serIP = address.toString();//获取IP
  43. QString serPort = ui->lineEdit_Port->text();//获取端口
  44. m_Server->listen((QHostAddress)serIP,serPort.toUInt());//启动监听
  45. ui->pushButton_StartServer->setText("关闭服务器");
  46. }else if(ui->pushButton_StartServer->text() == "关闭服务器")
  47. {
  48. m_Server->close();//关闭服务器
  49. ui->pushButton_StartServer->setText("启动服务器");
  50. }
  51. }

服务器类:

  1. //.h
  2. class Server : public QTcpServer
  3. {
  4. Q_OBJECT
  5. public:
  6. explicit Server(QObject *parent = Q_NULLPTR);
  7. ~Server();
  8. private:
  9. void incomingConnection(int sockDesc); //QTcpServer中被重写的函数,该函数在客户端接入时被调用
  10. private slots:
  11. void clientDisconnected(int sockDesc); //当产生客户端断开连接时向上层发送信号
  12. private:
  13. Widget *m_widget; //上层界面的句柄 便于底层 服务器进程类的 信号量直接连接到界面处理函数
  14. QList<int> m_socketList; //服务器Socket ID链表
  15. };
  16. //.cpp
  17. //这里的Server类继承于QTcpServer,
  18. //重写其中的void incomingConnection(int sockDesc)方法,
  19. //该方法在有客户端接入时自动调用。
  20. //每当一个新的客户端连接时,通过标识码socketDescriptor,实现与对应的客户端通信
  21. void Server::incomingConnection(int sockDesc)
  22. {
  23. m_socketList.append(sockDesc);//客户端ID 加入链表
  24. ServThread *thread = new ServThread(sockDesc); //创建服务器处理进程
  25. m_widget->showNewConnection(sockDesc); //界面提示,新客户端接入
  26. //服务器进程发出消息,告诉服务器,XX客户端断开连接
  27. connect(thread, SIGNAL(disconnectTCP(int)), this, SLOT(clientDisconnected(int)));
  28. //服务器进程发出消息给窗口,从哪个ip收到数据,槽函数由窗口构建
  29. connect(thread, SIGNAL(dataReady(const QString&, const QByteArray&)),
  30. m_widget, SLOT(recvData(const QString&, const QByteArray&)));
  31. //窗口向服务器进程发出信号 以客户端ID 为标识,发出数据,槽函数由服务器进程构建
  32. connect(m_widget, SIGNAL(sendData(int, const QByteArray&)),
  33. thread, SLOT(sendDataSlot(int, const QByteArray&)));
  34. //启动进程
  35. thread->start();
  36. }
  37. //这是一个槽函数 用于在界面上显示服务器断开了
  38. void Server::clientDisconnected(int sockDesc)
  39. {
  40. m_widget->showDisconnection(sockDesc);
  41. }

服务器通讯线程类

  1. //.h
  2. class ServThread : public QThread
  3. {
  4. Q_OBJECT
  5. public:
  6. explicit ServThread(int sockDesc, QObject *parent = Q_NULLPTR);
  7. ~ServThread();
  8. private:
  9. void run(void);
  10. public slots:
  11. void sendDataSlot(int sockDesc, const QByteArray &data);
  12. signals:
  13. void dataReady(const QString &ip, const QByteArray &data);
  14. void sendData(int sockDesc, const QByteArray &data);
  15. void disconnectTCP(int sockDesc);
  16. private slots:
  17. void recvDataSlot(const QString &ip, const QByteArray &data);
  18. void disconnectToHost(void);
  19. private:
  20. ServSocket *m_socket;
  21. int m_sockDesc;
  22. };
  23. //.c
  24. void ServThread:: sendDataSlot(int sockDesc, const QByteArray &data)
  25. {
  26. emit sendData(sockDesc, data);
  27. }
  28. void ServThread:: recvDataSlot(const QString &ip, const QByteArray &data)
  29. {
  30. emit dataReady(ip, data);
  31. }
  32. void ServThread:: disconnectToHost(void)
  33. {
  34. emit disconnectTCP(m_sockDesc);
  35. m_socket->disconnectFromHost();//断开连接
  36. this->quit();
  37. }
  38. void ServThread::run(void)
  39. {
  40. m_socket = new ServSocket(m_sockDesc);
  41. if (!m_socket->setSocketDescriptor(m_sockDesc)) {
  42. return ;
  43. }
  44. connect(m_socket, &ServSocket::disconnected, this, &ServThread::disconnectToHost);
  45. connect(m_socket, SIGNAL(dataReady(const QString&, const QByteArray&)),
  46. this, SLOT(recvDataSlot(const QString&, const QByteArray&)));
  47. connect(this, SIGNAL(sendData(int, const QByteArray&)),
  48. m_socket, SLOT(sendData(int, const QByteArray&)));
  49. this->exec();//在Qt中启动消息机制 龟腚
  50. }

服务器Socket类

  1. //.h
  2. class ServSocket: public QTcpSocket
  3. {
  4. Q_OBJECT
  5. public:
  6. explicit ServSocket(int sockDesc, QObject *parent = Q_NULLPTR);
  7. ~ServSocket();
  8. signals:
  9. void dataReady(const QString &ip, const QByteArray &data);
  10. public slots:
  11. void recvData(void);
  12. void sendData(int id, const QByteArray &data);
  13. private:
  14. int m_sockDesc;
  15. };
  16. //.c
  17. ServSocket::ServSocket(int sockDesc,QObject *parent) :QTcpSocket(parent)
  18. {
  19. m_sockDesc = sockDesc;
  20. connect(this,SIGNAL(readyRead()),this,SLOT(recvData()));//底层信号readyRead -> recvDate
  21. }
  22. ServSocket::~ServSocket()
  23. {
  24. }
  25. void ServSocket:: recvData()
  26. {
  27. QString ip = peerAddress().toString().remove(0, 7);
  28. QByteArray data = readAll();
  29. emit dataReady(ip, data);
  30. }
  31. void ServSocket:: sendData(int id, const QByteArray &data)
  32. {
  33. if (id == m_sockDesc && !data.isEmpty()) {
  34. this->write(data);
  35. }
  36. }

源码下载链接

https://download.csdn.net/download/zhaopeng6b/14193041

 

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

闽ICP备14008679号