• Qt 实现简单的TCP通信


    这段时间用到了QT的TCP通信,做了初步的学习与尝试,编写了一个客户端和服务器基于窗口通信的小例程。

    使用QT的网络套接字需要.pro文件中加入一句:

    QT += network

    一、客户端

    1、客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:

    (1)创建QTcpSocket套接字对象

    socket = new QTcpSocket();

    (2)使用这个对象连接服务器

    socket->connectToHost(IP, port);

    (3)使用write函数向服务器发送数据

    socket->write(data);

    (4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据

    1 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
    2  
    3 void MainWindow::socket_Read_Data()
    4 {
    5     QByteArray buffer;
    6     //读取缓冲区数据
    7     buffer = socket->readAll();
    8 }

    (5)断开与服务器的连接(关于close()和disconnectFromHost()的区别,可以按F1看帮助)

    socket->disconnectFromHost();

    2、以下是客户端的例程

    首先是mainwindow.h文件:

     1 //mainwindow.h
     2 #ifndef MAINWINDOW_H
     3 #define MAINWINDOW_H
     4  
     5 #include <QMainWindow>
     6 #include <QTcpSocket>
     7  
     8 namespace Ui {
     9 class MainWindow;
    10 }
    11  
    12 class MainWindow : public QMainWindow
    13 {
    14     Q_OBJECT
    15  
    16 public:
    17     explicit MainWindow(QWidget *parent = 0);
    18     ~MainWindow();
    19  
    20 private slots:
    21  
    22     void on_pushButton_Connect_clicked();
    23  
    24     void on_pushButton_Send_clicked();
    25  
    26     void socket_Read_Data();
    27  
    28     void socket_Disconnected();
    29  
    30 private:
    31     Ui::MainWindow *ui;
    32     QTcpSocket *socket;
    33 };
    34  
    35 #endif // MAINWINDOW_H

    然后是mainwindow.cpp文件:

     1 //mainwindow.cpp
     2 #include "mainwindow.h"
     3 #include "ui_mainwindow.h"
     4  
     5 MainWindow::MainWindow(QWidget *parent) :
     6     QMainWindow(parent),
     7     ui(new Ui::MainWindow)
     8 {
     9     ui->setupUi(this);
    10  
    11     socket = new QTcpSocket();
    12  
    13     //连接信号槽
    14     QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
    15     QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
    16  
    17     ui->pushButton_Send->setEnabled(false);
    18     ui->lineEdit_IP->setText("127.0.0.1");
    19     ui->lineEdit_Port->setText("8765");
    20  
    21 }
    22  
    23 MainWindow::~MainWindow()
    24 {
    25     delete this->socket;
    26     delete ui;
    27 }
    28  
    29 void MainWindow::on_pushButton_Connect_clicked()
    30 {
    31     if(ui->pushButton_Connect->text() == tr("连接"))
    32     {
    33         QString IP;
    34         int port;
    35  
    36         //获取IP地址
    37         IP = ui->lineEdit_IP->text();
    38         //获取端口号
    39         port = ui->lineEdit_Port->text().toInt();
    40  
    41         //取消已有的连接
    42         socket->abort();
    43         //连接服务器
    44         socket->connectToHost(IP, port);
    45  
    46         //等待连接成功
    47         if(!socket->waitForConnected(30000))
    48         {
    49             qDebug() << "Connection failed!";
    50             return;
    51         }
    52         qDebug() << "Connect successfully!";
    53  
    54         //发送按键使能
    55         ui->pushButton_Send->setEnabled(true);
    56         //修改按键文字
    57         ui->pushButton_Connect->setText("断开连接");
    58     }
    59     else
    60     {
    61         //断开连接
    62         socket->disconnectFromHost();
    63         //修改按键文字
    64         ui->pushButton_Connect->setText("连接");
    65         ui->pushButton_Send->setEnabled(false);
    66     }
    67 }
    68  
    69 void MainWindow::on_pushButton_Send_clicked()
    70 {
    71     qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
    72      //获取文本框内容并以ASCII码形式发送
    73     socket->write(ui->textEdit_Send->toPlainText().toLatin1());
    74     socket->flush();
    75 }
    76  
    77 void MainWindow::socket_Read_Data()
    78 {
    79     QByteArray buffer;
    80     //读取缓冲区数据
    81     buffer = socket->readAll();
    82     if(!buffer.isEmpty())
    83     {
    84         QString str = ui->textEdit_Recv->toPlainText();
    85         str+=tr(buffer);
    86         //刷新显示
    87         ui->textEdit_Recv->setText(str);
    88     }
    89 }
    90  
    91 void MainWindow::socket_Disconnected()
    92 {
    93     //发送按键失能
    94     ui->pushButton_Send->setEnabled(false);
    95     //修改按键文字
    96     ui->pushButton_Connect->setText("连接");
    97     qDebug() << "Disconnected!";
    98 }

    最后是ui的设计:

    二、服务器

    1、服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:

    (1)创建QTcpSever对象

    server = new QTcpServer();

    (2)侦听一个端口,使得客户端可以使用这个端口访问服务器

    server->listen(QHostAddress::Any, port);

    (3)当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问

    1 connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
    2  
    3 void MainWindow::server_New_Connect()
    4 {
    5     //获取客户端连接
    6     socket = server->nextPendingConnection();
    7 }

    (4)使用socket的write函数向客户端发送数据

    socket->write(data);

    (5)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据

    1 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
    2  
    3 void MainWindow::socket_Read_Data()
    4 {
    5     QByteArray buffer;
    6     //读取缓冲区数据
    7     buffer = socket->readAll();
    8 }

    (6)取消侦听

    server->close();

    2、以下是服务器的例程

    首先是mainwindow.h文件:

     1 //mainwindow.h
     2 #ifndef MAINWINDOW_H
     3 #define MAINWINDOW_H
     4  
     5 #include <QMainWindow>
     6 #include <QTcpServer>
     7 #include <QTcpSocket>
     8  
     9 namespace Ui {
    10 class MainWindow;
    11 }
    12  
    13 class MainWindow : public QMainWindow
    14 {
    15     Q_OBJECT
    16  
    17 public:
    18     explicit MainWindow(QWidget *parent = 0);
    19     ~MainWindow();
    20  
    21 private slots:
    22     void on_pushButton_Listen_clicked();
    23  
    24     void on_pushButton_Send_clicked();
    25  
    26     void server_New_Connect();
    27  
    28     void socket_Read_Data();
    29  
    30     void socket_Disconnected();
    31  
    32 private:
    33     Ui::MainWindow *ui;
    34     QTcpServer* server;
    35     QTcpSocket* socket;
    36 };
    37  
    38 #endif // MAINWINDOW_H

    然后是mainwindow.cpp文件:

      1 #include "mainwindow.h"
      2 #include "ui_mainwindow.h"
      3  
      4 MainWindow::MainWindow(QWidget *parent) :
      5     QMainWindow(parent),
      6     ui(new Ui::MainWindow)
      7 {
      8     ui->setupUi(this);
      9  
     10     ui->lineEdit_Port->setText("8765");
     11     ui->pushButton_Send->setEnabled(false);
     12  
     13     server = new QTcpServer();
     14  
     15     //连接信号槽
     16     connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
     17 }
     18  
     19 MainWindow::~MainWindow()
     20 {
     21     server->close();
     22     server->deleteLater();
     23     delete ui;
     24 }
     25  
     26 void MainWindow::on_pushButton_Listen_clicked()
     27 {
     28     if(ui->pushButton_Listen->text() == tr("侦听"))
     29     {
     30         //从输入框获取端口号
     31         int port = ui->lineEdit_Port->text().toInt();
     32  
     33         //监听指定的端口
     34         if(!server->listen(QHostAddress::Any, port))
     35         {
     36             //若出错,则输出错误信息
     37             qDebug()<<server->errorString();
     38             return;
     39         }
     40         //修改按键文字
     41         ui->pushButton_Listen->setText("取消侦听");
     42         qDebug()<< "Listen succeessfully!";
     43     }
     44     else
     45     {
     46 /*
     47         //如果正在连接(点击侦听后立即取消侦听,若socket没有指定对象会有异常,应修正——2017.9.30)
     48         if(socket->state() == QAbstractSocket::ConnectedState)
     49         {
     50             //关闭连接
     51             socket->disconnectFromHost();
     52         }
     53 */
     54         socket->abort();
     55         //取消侦听
     56         server->close();
     57         //修改按键文字
     58         ui->pushButton_Listen->setText("侦听");
     59         //发送按键失能
     60         ui->pushButton_Send->setEnabled(false);
     61     }
     62  
     63 }
     64  
     65 void MainWindow::on_pushButton_Send_clicked()
     66 {
     67     qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
     68     //获取文本框内容并以ASCII码形式发送
     69     socket->write(ui->textEdit_Send->toPlainText().toLatin1());
     70     socket->flush();
     71 }
     72  
     73 void MainWindow::server_New_Connect()
     74 {
     75     //获取客户端连接
     76     socket = server->nextPendingConnection();
     77     //连接QTcpSocket的信号槽,以读取新数据
     78     QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
     79     QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
     80     //发送按键使能
     81     ui->pushButton_Send->setEnabled(true);
     82  
     83     qDebug() << "A Client connect!";
     84 }
     85  
     86 void MainWindow::socket_Read_Data()
     87 {
     88     QByteArray buffer;
     89     //读取缓冲区数据
     90     buffer = socket->readAll();
     91     if(!buffer.isEmpty())
     92     {
     93         QString str = ui->textEdit_Recv->toPlainText();
     94         str+=tr(buffer);
     95         //刷新显示
     96         ui->textEdit_Recv->setText(str);
     97     }
     98 }
     99  
    100 void MainWindow::socket_Disconnected()
    101 {
    102     //发送按键失能
    103     ui->pushButton_Send->setEnabled(false);
    104     qDebug() << "Disconnected!";
    105 }

    最后是ui的设计:

     三、运行结果

  • 相关阅读:
    树状数组&线段树
    8月7日小练
    8月6日小练
    LID&LDS 的另外一种算法
    LCS,LIS,LCIS
    8-11-Exercise
    8-10-Exercise
    线段树
    8-7-Exercise
    8-6-Exercise
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14743616.html
Copyright © 2020-2023  润新知