• qt5之网络通信


    QT5 TCP网络通讯

    • 服务器与客户端建立连接listen() - connectToHost();  触发newPendingConnect信号
    • 实时数据通讯write(); read();  触发readyRead信号
    • 通讯主要使用的类:
    • QTcpServer  Class

      QTcpServer类提供了一个基于TCP的服务器。
      这个类可以接受传入的TCP连接。您可以指定端口或让QTcpServer自动选择一个端口。您可以收听特定地址或所有机器的地址。
      调用listen()让服务器侦听传入的连接。每次客户端连接到服务器时,都会发出newConnection()信号。

    • QTcpSocket Class

      QTcpSocket类提供了一个TCP套接字。
      TCP(传输控制协议)是一种可靠的,面向流的,面向连接的传输协议。 它特别适合连续传输数据。
      QTcpSocket是QAbstractSocket的一个方便的子类,它允许你建立一个TCP连接并传输数据流。

    • 建立连接:

      服务器端以监听的方式监听客服端是否有连接请求

      客户端以调用connectToHost()函数主动连接服务器端

    • tcp协议服务器端实现流程

      建立服务器对象

      listen服务器, 通过建立的服务器 监听指定地址/端口的客服端;判断是否有客户连接有连接就触发newConnection();

    • 通过connect处理newConnection()信号;
      server = new QTcpServer(this); //建立一个服务器对象
          server->listen(QHostAddress::Any, 8000);//通过建立的服务器监听指定ip地址及端口号的客服端,如不指定端口号,系统会随机分配
          connect(server, QTcpServer::newConnection,
          [=]()
          {
              qDebug() << "有连接进来";
          }
          );

      tcp协议客户端实现流程

      建立QTcpSocket套节字(ip,端口)

      通过套节字connectToHost()函数主动连接服务器;连接成功则触发服务器QTcpServer::newConnection信号;并发送套节字到服务器端;

      关闭连接;

      QTcpSocket Sc(this);
      Sc.connectToHost("127.0.0.1", 8888);//实际代码中参数要进行类型转化
      Sc.close();

      实时通讯:

      • 客户端到服务器端通讯
      1. 当客户端与服务器端建立连接后;
      2. 客户端与服务器端通讯在客户端通过套节字对象调用write()函数发送上传内容;
      3. 服务器端有客户端数据写入时服务器端会自动调用readyread信号
      4. 服务器端在connect中处理readyread信号,并由nextPendingConnection()函数接收客户端发送的套节字;
      5. 服务器端对接收的套节字进行相应处理,即完成一次客户端到服务器端的通讯
      • 服务器端到客户端的通讯
      1. 当客户端与服务器端建立连接后;
      2. 服务器通过套节字对象调用write()函数发送上传内容;客户端会触发readyread信号
      3. 客户端在connect中处理readyread信号
      客户端到服务器端实现代码:
    • 服务器端头文件widget.h
      #ifndef WIDGET_H
      #define WIDGET_H
      
      #include <QWidget>
      #include <QTcpServer>
      #include <QTcpSocket>
      namespace Ui {
      class Widget;
      }
      
      class Widget : public QWidget
      {
          Q_OBJECT
      
      public:
          explicit Widget(QWidget *parent = 0);
          ~Widget();
      
      private slots:
          void on_buttonsend_clicked();
      
      private:
          Ui::Widget *ui;
      
          QTcpServer *server; //建立服务器对象
          QTcpSocket *socket; //套节字对象
          QByteArray tp;   //
      };
      
      #endif // WIDGET_H

      服务器端cpp文件 widget.cpp

      #include "widget.h"
      #include "ui_widget.h"
      #include <QDebug>
      
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
          setWindowTitle("服务器");
          tp = nullptr;
      
          server = new QTcpServer(this);
          server->listen(QHostAddress::Any, 8000);
          connect(server, QTcpServer::newConnection,
                  [=]()
          {
              socket = server->nextPendingConnection();
              connect(socket, &QTcpSocket::readyRead, [=]()
              {
                  tp = socket->readAll();
                  ui->testdis->append(tp);
              });
          }
          );
      
      }
      
      Widget::~Widget()
      {
          delete ui;
      }
      
      void Widget::on_buttonsend_clicked()
      {
          socket->write(ui->textEdit->toPlainText().toUtf8());
      }

      客户端头文件socket.h:

      #ifndef SOCKET_H
      #define SOCKET_H
      
      #include <QWidget>
      #include <QTcpSocket>
      #include <QHostAddress>
      
      namespace Ui {
      class socket;
      }
      
      class socket : public QWidget
      {
          Q_OBJECT
      
      public:
          explicit socket(QWidget *parent = 0);
          ~socket();
      
      private slots:
      
          void on_buttonLink_clicked();
      
          void on_buttonsend_clicked();
      
          void on_serverclose_clicked();
      
      private:
          Ui::socket *ui;
      
          QTcpSocket *sock;
          QHostAddress adrs;
          quint16 port;
      };
      
      #endif // SOCKET_H

      客户端cpp文件socket.cpp

    • #include "socket.h"
      #include "ui_socket.h"
      
      socket::socket(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::socket)
      {
          ui->setupUi(this);
          sock = new QTcpSocket(this);
          setWindowTitle("张三");
          connect(sock, &QTcpSocket::readyRead,
                  [=]()
          {
             ui->textdis->append(sock->readAll());
          });
      }
      
      socket::~socket()
      {
          delete ui;
      }
      
      void socket::on_buttonLink_clicked()
      {
          QString ip = ui->serverIP->text();
          QString p = ui->serverPort->text();
          sock->connectToHost(ip, p.toUShort());
      }
      
      void socket::on_buttonsend_clicked()
      {
          QString temp = ui->textEdit->toPlainText();
          if(!temp.isEmpty())sock->write(temp.toUtf8());
      }
      
      void socket::on_serverclose_clicked()
      {
          sock->close();
      }

      main.cpp文件

      #include "widget.h"
      #include <QApplication>
      #include "socket.h"
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          Widget w;
          w.show();
          socket w1;
          w1.show();
      
          return a.exec();
      }

    • 运行的效果如图所示

    • 后续的通信例子还在学习中,本文的参考链接:

    • (1)https://www.cnblogs.com/flowingwind/p/8348519.html

    • (2)https://www.cnblogs.com/findumars/p/5838531.html
    • (3)https://blog.csdn.net/pk124729136/article/details/8087609
  • 相关阅读:
    C# 使用Dev控件为gridView添加复选框,实现多选和单选
    C# 关于LINQ基础随笔
    Camstar客制化开发做查询操作(Designer中存放SQL语句)
    ASP.NET 实现自动登录(自定义自动登录时间期限)
    ASP.NET 页面生命周期-动态控件编程(动态添加控件并使用动态控件值)
    Camstar客制化开发查询数据库数据并显示在JQDataGrid表中(SQL语句编写在UserQuery中)同时获取JQDataGrid中值回传到Designer中
    Camstar客制化开发查询数据库数据并显示在JQDataGrid表中(SQL语句编写在代码中)
    WPF开发中常用的几种布局元素
    Cocos2dx 内存管理机制(1)
    cocos2dx 坐标系统详解
  • 原文地址:https://www.cnblogs.com/tansuoxinweilai/p/10275164.html
Copyright © 2020-2023  润新知