百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

正点原子I.MX6U嵌入式Qt开发指南:第十一章《网络编程》

toyiye 2024-08-17 00:19 7 浏览 0 评论

今日头条/西瓜视频/抖音短视频 同名:正点原子

原子哥今日头条/西瓜视频/抖音短视频账号:正点原子-原子哥

感谢各位的关注和支持,你们的关注和支持是正点原子无限前进的动力。

第十一章《网络编程》

由于本章内容较多,所以第十一章《网络编程》将会分为几个部分进行内容的发布,更多文章内容请持续关注今日头条正点原子官方账号。

Qt网络模块为我们提供了编写TCP / IP客户端和服务器的类。它提供了较低级别的类,例如代表低级网络概念的QTcpSocket,QTcpServer和QUdpSocket,以及诸如QNetworkRequest,QNetworkReply和QNetworkAccessManager之类的高级类来执行使用通用协议的网络操作。 它还提供了诸如QNetworkConfiguration,QNetworkConfigurationManager和QNetworkSession等类,实现承载管理。

想要在程序中使用Qt网络模块,我们需要在pro项目配置文件里增加下面的一条语句。

QT += network

11.1获取本机的网络信息

为什么先写获取本机网络信息的内容呢?在建立网络通信之前我们至少得获取对方的IP地址。在网络应用中,经常需要用到本机的主机名、IP地址、MAC地址等网络信息,通常通在Windows通过过调出命令行cmd窗口输入ipconfig或者在Linux系统中使用ifconfig命令就可以查看相关信息了,在这里我们利用Qt做出一个可以查询的界面和功能出来,为了后面的网络编程打下一个简单的基础。

Qt提供了QHostInfo和QNetworkInterface类可以用于此类信息查询。更多关于QHostInfo和QNetworkInterface的相关函数可以在Qt的帮助文档中找到。下面我们写代码时会使用到相关的函数,有清楚的注释。

11.1.1应用实例

本例目的:了解如何通过QHostInfo和QNetworkInterface类获取本地网络所有接口的信息。

例07_networkhostinfo,获取本机网络接口信息(难度:一般)。项目路径为Qt/2/07_networkhostinfo。本例获取本机的网络接口信息,打印在文本浏览框上,点击按钮可直接获取,为了清楚看见是重新获取的过程,本例点击获取本机信息按钮后延时1s去刷新获取的信息。点击另一个清空文本信息按钮可以清空文本浏览框上的文本内容。

项目文件07_networkhostinfo.pro文件第一行添加的代码部分如下。

07_ networkhostinfo.pro编程后的代码

1   QT       += core gui network

2 

3   greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

4 

5   CONFIG += c++11

6 

7   # The following define makes your compiler emit warnings if you use

8   # any Qt feature that has been marked deprecated (the exact warnings

9   # depend on your compiler). Please consult the documentation of the

10  # deprecated API in order to know how to port your code away from it.

11  DEFINES += QT_DEPRECATED_WARNINGS

12

13  # You can also make your code fail to compile if it uses deprecated APIs.

14  # In order to do so, uncomment the following line.

15  # You can also select to disable deprecated APIs only up to a certain version of Qt.

16  #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

17

18  SOURCES += \

19      main.cpp \

20      mainwindow.cpp

21

22  HEADERS += \

23      mainwindow.h

24

25  # Default rules for deployment.

26  qnx: target.path = /tmp/${TARGET}/bin

27  else: unix:!android: target.path = /opt/${TARGET}/bin

28  !isEmpty(target.path): INSTALLS += target

在头文件“mainwindow.h”具体代码如下。

mainwindow.h编程后的代码

    /******************************************************************

    Copyright ? Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.

    * @projectName   07_networkhostinfo

    * @brief         mainwindow.h

    * @author        Deng Zhimao

    * @email         1252699831@qq.com

    * @net            www.openedv.com

    * @date           2021-04-10

    *******************************************************************/

1   #ifndef MAINWINDOW_H

2   #define MAINWINDOW_H

3 

4   #include <QMainWindow>

5   #include <QPushButton>

6   #include <QTextBrowser>

7   #include <QVBoxLayout>

8   #include <QHBoxLayout>

9   #include <QTimer>

10

11  class MainWindow : public QMainWindow

12  {

13      Q_OBJECT

14

15  public:

16      MainWindow(QWidget *parent = nullptr);

17      ~MainWindow();

18

19  private:

20      /* 点击获取和清空文本按钮 */

21      QPushButton *pushButton[2];

22

23      /* 文本浏览框用于显示本机的信息 */

24      QTextBrowser *textBrowser;

25

26      /* 水平Widget容器和垂直Widget容器*/

27      QWidget *hWidget;

28      QWidget *vWidget;

29

30      /* 水平布局和垂直布局 */

31      QHBoxLayout *hBoxLayout;

32      QVBoxLayout *vBoxLayout;

33

34      /* 定时器 */

35      QTimer *timer;

36

37      /* 获取本机的网络的信息,返回类型是QString */

38      QString getHostInfo();

39

40  private slots:

41      /* 定时器槽函数,点击按钮后定时触发 */

42      void timerTimeOut();

43

44      /* 显示本机信息 */

45      void showHostInfo();

46

47      /* 启动定时器 */

48      void timerStart();

49

50      /* 清空textBrowser的信息 */

51      void clearHostInfo();

52  };

53  #endif // MAINWINDOW_H

54

头文件里主要是声明两个按钮和一个文本浏览框。另外还有一个定时器,声明一些槽函数,比较简单。

在源文件“mainwindow.cpp”具体代码如下。

mainwindow.cpp编程后的代码

    /******************************************************************

    Copyright ? Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.

    * @projectName   07_networkhostinfo

    * @brief         mainwindow.cpp

    * @author        Deng Zhimao

    * @email         1252699831@qq.com

    * @net            www.openedv.com

    * @date           2021-04-10

    *******************************************************************/

1   #include "mainwindow.h"

2   #include <QNetworkInterface>

3   #include <QHostInfo>

4   #include <QThread>

5   #include <QDebug>

6  

7   MainWindow::MainWindow(QWidget *parent)

8       : QMainWindow(parent)

9   {

10      /* 设置位置与大小 */

11      this->setGeometry(0, 0, 800, 480);

12 

13      /* 点击获取本地信息按钮和清空文本按钮 */

14      pushButton[0] = new QPushButton();

15      pushButton[1] = new QPushButton();

16 

17      pushButton[0]->setText("获取本机信息");

18      pushButton[1]->setText("清空文本信息");

19 

20      /* 按钮的大小根据文本自适应,

21       * 注意setSizePolicy需要在布局中使用 */

22      pushButton[0]->setSizePolicy(QSizePolicy::Fixed,

23                                   QSizePolicy::Fixed);

24      pushButton[1]->setSizePolicy(QSizePolicy::Fixed,

25                                   QSizePolicy::Fixed);

26 

27      /* 水平Widget和垂直Widget用于添加布局 */

28      hWidget = new QWidget();

29      vWidget = new QWidget();

30 

31      /* 水平布局和垂直布局 */

32      hBoxLayout = new QHBoxLayout();

33      vBoxLayout = new QVBoxLayout();

34 

35      /* 文本浏览框 */

36      textBrowser = new QTextBrowser();

37 

38      /* 添加到水平布局 */

39      hBoxLayout->addWidget(pushButton[0]);

40      hBoxLayout->addWidget(pushButton[1]);

41 

42      /* 将水平布局设置为hWidget的布局 */

43      hWidget->setLayout(hBoxLayout);

44 

45      /* 将文本浏览框和hWidget添加到垂直布局 */

46      vBoxLayout->addWidget(textBrowser);

47      vBoxLayout->addWidget(hWidget);

48 

49      /* 将垂直布局设置为vWidget的布局 */

50      vWidget->setLayout(vBoxLayout);

51 

52      /* 设置vWidget为中心部件 */

53      setCentralWidget(vWidget);

54 

55      /* 定时器初始化 */

56      timer = new QTimer();

57 

58      /* 信号槽连接 */

59      connect(pushButton[0], SIGNAL(clicked()),

60              this, SLOT(timerStart()));

61      connect(pushButton[1], SIGNAL(clicked()),

62              this, SLOT(clearHostInfo()));

63      connect(timer, SIGNAL(timeout()),

64              this, SLOT(timerTimeOut()));

65  }

66 

67  MainWindow::~MainWindow()

68  {

69  }

70 

71 

72  void MainWindow::timerStart()

73  {

74      /* 清空文本 */

75      textBrowser->clear();

76 

77      /* 定时1s */

78      timer->start(1000);

79  }

80 

81  void MainWindow::timerTimeOut()

82  {

83      /* 显示本机信息 */

84      showHostInfo();

85 

86      /* 停止定时器 */

87      timer->stop();

88  }

89 

90  QString MainWindow::getHostInfo()

91  {

92      /* 通过QHostInfo的localHostName函数获取主机名称 */

93      QString str = "主机名称:" + QHostInfo::localHostName() + "\n";

94 

95      /* 获取所有的网络接口,

96       * QNetworkInterface类提供主机的IP地址和网络接口的列表 */

97      QList<QNetworkInterface> list

98              = QNetworkInterface::allInterfaces();

99 

100     /* 遍历list */

101     foreach (QNetworkInterface interface, list) {

102         str+= "网卡设备:" + interface.name() + "\n";

103         str+= "MAC地址:" + interface.hardwareAddress() + "\n";

104

105         /* QNetworkAddressEntry类存储IP地址子网掩码和广播地址 */

106         QList<QNetworkAddressEntry> entryList

107                 = interface.addressEntries();

108

109         /* 遍历entryList */

110         foreach (QNetworkAddressEntry entry, entryList) {

111             /* 过滤IPv6地址,只留下IPv4 */

112             if (entry.ip().protocol() ==

113                     QAbstractSocket::IPv4Protocol) {

114                 str+= "IP 地址:" + entry.ip().toString() + "\n";

115                 str+= "子网掩码:" + entry.netmask().toString() + "\n";

116                 str+= "广播地址:" + entry.broadcast().toString() + "\n\n";

117             }

118         }

119     }

120

121     /* 返回网络信息 */

122     return str;

123 }

124

125 void MainWindow::showHostInfo()

126 {

127     /* 获取本机信息后显示到textBrowser */

128     textBrowser->insertPlainText(getHostInfo());

129 }

130

131 void MainWindow::clearHostInfo()

132 {

133     /* 判断textBrowser是否为空,如果不为空则清空文本 */

134     if (!textBrowser->toPlainText().isEmpty())

135

136         /* 清空文本 */

137         textBrowser->clear();

138 }

第90~123行,是本例最重要的代码。

第93行,通过QHostInfo的localHostName函数获取主机名称。

第97~98行,通过QNetworkInterface::allInterfaces()获取网络接口列表list类存储IP地址子网掩码和广播地址。如果我们用qDebug()函数打印出list,可以发现获取了所有的网络信息。而我们要提取网络里面的网络信息使用QNetworkAddressEntry。

第106~107行,使用QNetworkAddressEntry从interface接口里使用函数addressEntries(),获取所有的条目。就可以使用QNetworkAddressEntry的对象entry获取IP地址子网掩码和广播地址。

第110~118行,因为获取的entries在一个QNetworkInterface下可能有两个IP,分别是ipv4和ipv6。这里使用ip().protocol()来判断协议的类型,只留下ipv4类型的信息。筛选信息在我们写程序常常需要的。

11.1.2程序运行效果

点击获取本机信息,在文本浏览框内就打印出本机的网络信息(包括了主机名,网卡名,ip地址等)。这里因为过滤掉了IPv6的信息。通常一个网卡有两个ip地址,一个是ipv4,另一个是ipv6的地址。下面的网卡设备lo,是本地回环网卡。另一个ens33是虚拟机的网卡,由VMware虚拟出来的。点击清空文本信息会清空文本浏览框里的网络信息。

11.2 TCP通信

11.2.1 TCP简介

TCP协议(Transmission Control Protocol)全称是传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。

TCP通信必须先建立TCP连接,通信端分为客户端和服务端。服务端通过监听某个端口来监听是否有客户端连接到来,如果有连接到来,则建立新的socket连接;客户端通过ip和port连接服务端,当成功建立连接之后,就可进行数据的收发了。需要注意的是,在Qt中,Qt把socket当成输入输出流来对待的,数据的收发是通过read()和write()来进行的,需要与我们常见的send()与recv()进行区分。

TCP客户端与服务端通信示意图如下。

11.2.2 TCP服务端应用实例

本例目的:了解TCP服务端的使用。

例08_tcpserver,TCP服务端(难度:一般)。项目路径为Qt/2/08_tcpserver。本例大体流程首先获取本地IP地址。创建一个tcpSocket套接字,一个tcpServer服务端。点击监听即监听本地的主机IP地址和端口,同时等待服务端的连接。此程序需要结合客户端一起使用。

项目文件08_tcpserver.pro文件第一行添加的代码部分如下。

08_tcpserver.pro编程后的代码

1   QT       += core gui network

2 

3   greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

4 

5   CONFIG += c++11

6 

7   # The following define makes your compiler emit warnings if you use

8   # any Qt feature that has been marked deprecated (the exact warnings

9   # depend on your compiler). Please consult the documentation of the

10  # deprecated API in order to know how to port your code away from it.

11  DEFINES += QT_DEPRECATED_WARNINGS

12

13  # You can also make your code fail to compile if it uses deprecated APIs.

14  # In order to do so, uncomment the following line.

15  # You can also select to disable deprecated APIs only up to a certain version of Qt.

16  #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

17

18  SOURCES += \

19      main.cpp \

20      mainwindow.cpp

21

22  HEADERS += \

23      mainwindow.h

24

25  # Default rules for deployment.

26  qnx: target.path = /tmp/${TARGET}/bin

27  else: unix:!android: target.path = /opt/${TARGET}/bin

28  !isEmpty(target.path): INSTALLS += target

在头文件“mainwindow.h”具体代码如下。

mainwindow.h编程后的代码

    /******************************************************************

    Copyright ? Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.

    * @projectName   08_tcpserver

    * @brief         mainwindow.h

    * @author        Deng Zhimao

    * @email         1252699831@qq.com

    * @net            www.openedv.com

    * @date           2021-04-13

    *******************************************************************/

1   #ifndef MAINWINDOW_H

2   #define MAINWINDOW_H

3 

4   #include <QMainWindow>

5   #include <QTcpServer>

6   #include <QTcpSocket>

7   #include <QVBoxLayout>

8   #include <QHBoxLayout>

9   #include <QPushButton>

10  #include <QTextBrowser>

11  #include <QLabel>

12  #include <QComboBox>

13  #include <QSpinBox>

14  #include <QHostInfo>

15  #include <QLineEdit>

16  #include <QNetworkInterface>

17  #include <QDebug>

18

19  class MainWindow : public QMainWindow

20  {

21      Q_OBJECT

22

23  public:

24      MainWindow(QWidget *parent = nullptr);

25      ~MainWindow();

26

27  private:

28      /* tcp服务器 */

29      QTcpServer *tcpServer;

30

31      /* 通信套接字 */

32      QTcpSocket *tcpSocket;

33

34      /* 按钮 */

35      QPushButton *pushButton[4];

36

37      /* 标签文本 */

38      QLabel *label[2];

39

40      /* 水平容器 */

41      QWidget *hWidget[3];

42

43      /* 水平布局 */

44      QHBoxLayout *hBoxLayout[3];

45

46      /* 垂直容器 */

47      QWidget *vWidget;

48

49      /* 垂直布局 */

50      QVBoxLayout *vBoxLayout;

51

52      /* 文本浏览框 */

53      QTextBrowser *textBrowser;

54

55      /* 用于显示本地ip */

56      QComboBox *comboBox;

57

58      /* 用于选择端口 */

59      QSpinBox  *spinBox;

60

61      /* 文本输入框 */

62      QLineEdit *lineEdit;

63

64      /* 存储本地的ip列表地址 */

65      QList<QHostAddress> IPlist;

66

67      /* 获取本地的所有ip */

68      void getLocalHostIP();

69

70  private slots:

71      /* 客户端连接处理槽函数 */

72      void clientConnected();

73

74      /* 开始监听槽函数 */

75      void startListen();

76

77      /* 停止监听槽函数 */

78      void stopListen();

79

80      /* 清除文本框时的内容 */

81      void clearTextBrowser();

82

83      /* 接收到消息 */

84      void receiveMessages();

85

86      /* 发送消息 */

87      void sendMessages();

88

89      /* 连接状态改变槽函数 */

90      void socketStateChange(QAbstractSocket::SocketState);

91  };

92  #endif // MAINWINDOW_H

头文件里主要是声明界面用的元素,及一些槽函数。重点是声明tcpServer和tcpSocket。

在源文件“mainwindow.cpp”具体代码如下。

mainwindow.cpp编程后的代码

    /******************************************************************

    Copyright ? Deng Zhimao Co., Ltd. 1990-2021. All rights reserved.

    * @projectName   08_tcpserver

    * @brief         mainwindow.cpp

    * @author        Deng Zhimao

    * @email         1252699831@qq.com

    * @net            www.openedv.com

    * @date           2021-04-13

    *******************************************************************/

1   #include "mainwindow.h"

2  

3   MainWindow::MainWindow(QWidget *parent)

4       : QMainWindow(parent)

5   {

6       /* 设置主窗体的位置与大小 */

7       this->setGeometry(0, 0, 800, 480);

8  

9       /* 实例化tcp服务器与tcp套接字 */

10      tcpServer = new QTcpServer(this);

11      tcpSocket = new QTcpSocket(this);

12 

13      /* 开始监听按钮 */

14      pushButton[0] = new QPushButton();

15      /* 停止监听按钮 */

16      pushButton[1] = new QPushButton();

17      /* 清空聊天文本按钮 */

18      pushButton[2] = new QPushButton();

19      /* 发送消息按钮 */

20      pushButton[3] = new QPushButton();

21 

22      /* 水平布局一 */

23      hBoxLayout[0] = new QHBoxLayout();

24      /* 水平布局二 */

25      hBoxLayout[1] = new QHBoxLayout();

26      /* 水平布局三 */

27      hBoxLayout[2] = new QHBoxLayout();

28      /* 水平布局四 */

29      hBoxLayout[3] = new QHBoxLayout();

30 

31      /* 水平容器一 */

32      hWidget[0] =  new QWidget();

33      /* 水平容器二 */

34      hWidget[1] =  new QWidget();

35      /* 水平容器三 */

36      hWidget[2] =  new QWidget();

37 

38      vWidget = new QWidget();

39      vBoxLayout = new QVBoxLayout();

40 

41      /* 标签实例化 */

42      label[0] = new QLabel();

43      label[1] = new QLabel();

44 

45      lineEdit = new QLineEdit();

46      comboBox = new QComboBox();

47      spinBox = new QSpinBox();

48      textBrowser = new QTextBrowser();

49 

50      label[0]->setText("监听IP地址:");

51      label[1]->setText("监听端口:");

52 

53      /* 设置标签根据文本文字大小自适应大小  */

54      label[0]->setSizePolicy(QSizePolicy::Fixed,

55                              QSizePolicy::Fixed);

56      label[1]->setSizePolicy(QSizePolicy::Fixed,

57                              QSizePolicy::Fixed);

58 

59      /* 设置端口号的范围,注意不要与主机的已使用的端口号冲突 */

60      spinBox->setRange(10000, 99999);

61 

62      pushButton[0]->setText("开始监听");

63      pushButton[1]->setText("停止监听");

64      pushButton[2]->setText("清空文本");

65      pushButton[3]->setText("发送消息");

66 

67      /* 设置停止监听状态不可用 */

68      pushButton[1]->setEnabled(false);

69 

70      /* 设置输入框默认的文本 */

71      lineEdit->setText("www.openedv.com正点原子论坛");

72 

73      /* 水平布局一添加内容 */

74      hBoxLayout[0]->addWidget(pushButton[0]);

75      hBoxLayout[0]->addWidget(pushButton[1]);

76      hBoxLayout[0]->addWidget(pushButton[2]);

77 

78      /* 设置水平容器一的布局为水平布局一 */

79      hWidget[0]->setLayout(hBoxLayout[0]);

80 

81      /* 水平布局二添加内容 */

82      hBoxLayout[1]->addWidget(label[0]);

83      hBoxLayout[1]->addWidget(comboBox);

84      hBoxLayout[1]->addWidget(label[1]);

85      hBoxLayout[1]->addWidget(spinBox);

86 

87      /* 设置水平容器二的布局为水平布局二 */

88      hWidget[1]->setLayout(hBoxLayout[1]);

89 

90      /* 水平布局三添加内容 */

91      hBoxLayout[2]->addWidget(lineEdit);

92      hBoxLayout[2]->addWidget(pushButton[3]);

93 

94      /* 设置水平容器三的布局为水平布局一 */

95      hWidget[2]->setLayout(hBoxLayout[2]);

96 

97      /* 垂直布局添加内容 */

98      vBoxLayout->addWidget(textBrowser);

99      vBoxLayout->addWidget(hWidget[1]);

100     vBoxLayout->addWidget(hWidget[0]);

101     vBoxLayout->addWidget(hWidget[2]);

102

103     /* 设置垂直容器的布局为垂直布局 */

104     vWidget->setLayout(vBoxLayout);

105

106     /* 居中显示 */

107     setCentralWidget(vWidget);

108

109     /* 获取本地ip */

110     getLocalHostIP();

111

112     /* 信号槽连接 */

113     connect(pushButton[0], SIGNAL(clicked()),

114             this, SLOT(startListen()));

115     connect(pushButton[1], SIGNAL(clicked()),

116             this, SLOT(stopListen()));

117     connect(pushButton[2], SIGNAL(clicked()),

118             this, SLOT(clearTextBrowser()));

119     connect(pushButton[3], SIGNAL(clicked()),

120             this, SLOT(sendMessages()));

121     connect(tcpServer, SIGNAL(newConnection()),

122             this, SLOT(clientConnected()));

123 }

124

125 MainWindow::~MainWindow()

126 {

127 }

128

129 /* 新的客户端连接 */

130 void MainWindow::clientConnected()

131 {

132     /* 获取客户端的套接字 */

133     tcpSocket = tcpServer->nextPendingConnection();

134     /* 客户端的ip信息 */

135     QString ip = tcpSocket->peerAddress().toString();

136     /* 客户端的端口信息 */

137     qint16 port = tcpSocket->peerPort();

138     /* 在文本浏览框里显示出客户端的连接信息 */

139     textBrowser->append("客户端已连接");

140     textBrowser->append("客户端ip地址:"

141                         + ip);

142     textBrowser->append("客户端端口:"

143                         + QString::number(port));

144

145     connect(tcpSocket, SIGNAL(readyRead()),

146             this, SLOT(receiveMessages()));

147     connect(tcpSocket, 

148             SIGNAL(stateChanged(QAbstractSocket::SocketState)),

149             this, 

150             SLOT(socketStateChange(QAbstractSocket::SocketState)));

151 }

152

153 /* 获取本地IP */

154 void MainWindow::getLocalHostIP()

155 {

156     // /* 获取主机的名称 */

157     // QString hostName = QHostInfo::localHostName();

158

159     // /* 主机的信息 */

160     // QHostInfo hostInfo = QHostInfo::fromName(hostName);

161

162     // /* ip列表,addresses返回ip地址列表,注意主机应能从路由器获取到

163     // * IP,否则可能返回空的列表(ubuntu用此方法只能获取到环回IP) */

164     // IPlist = hostInfo.addresses();

165     // qDebug()<<IPlist<<endl;

166

167     // /* 遍历IPlist */

168     // foreach (QHostAddress ip, IPlist) {

169     //      if (ip.protocol() == QAbstractSocket::IPv4Protocol)

170     //          comboBox->addItem(ip.toString());

171     //    }

172

173     /* 获取所有的网络接口,

174      * QNetworkInterface类提供主机的IP地址和网络接口的列表 */

175     QList<QNetworkInterface> list

176             = QNetworkInterface::allInterfaces();

177

178     /* 遍历list */

179     foreach (QNetworkInterface interface, list) {

180

181         /* QNetworkAddressEntry类存储IP地址子网掩码和广播地址 */

182         QList<QNetworkAddressEntry> entryList

183                 = interface.addressEntries();

184

185         /* 遍历entryList */

186         foreach (QNetworkAddressEntry entry, entryList) {

187             /* 过滤IPv6地址,只留下IPv4 */

188             if (entry.ip().protocol() ==

189                     QAbstractSocket::IPv4Protocol) {

190                 comboBox->addItem(entry.ip().toString());

191                 /* 添加到IP列表中 */

192                 IPlist<<entry.ip();

193             }

194         }

195     }

196 }

197

198 /* 开始监听 */

199 void MainWindow::startListen()

200 {

201     /* 需要判断当前主机是否有IP项 */

202     if (comboBox->currentIndex() != -1) {

203         qDebug()<<"start listen"<<endl;

204         tcpServer->listen(IPlist[comboBox->currentIndex()],

205                 spinBox->value());

206

207         /* 设置按钮与下拉列表框的状态 */

208         pushButton[0]->setEnabled(false);

209         pushButton[1]->setEnabled(true);

210         comboBox->setEnabled(false);

211         spinBox->setEnabled(false);

212

213         /* 在文本浏览框里显示出服务端 */

214         textBrowser->append("服务器IP地址:"

215                             + comboBox->currentText());

216         textBrowser->append("正在监听端口:"

217                             + spinBox->text());

218     }

219 }

220

221 /* 停止监听 */

222 void MainWindow::stopListen()

223 {

224     qDebug()<<"stop listen"<<endl;

225     /* 停止监听 */

226     tcpServer->close();

227

228     /* 如果是连接上了也应该断开,如果不断开客户端还能继续发送信息,

229      * 因为socket未断开,还在监听上一次端口 */

230     if (tcpSocket->state() == tcpSocket->ConnectedState)

231         tcpSocket->disconnectFromHost();

232

233     /* 设置按钮与下拉列表框的状态  */

234     pushButton[1]->setEnabled(false);

235     pushButton[0]->setEnabled(true);

236     comboBox->setEnabled(true);

237     spinBox->setEnabled(true);

238

239     /* 将停止监听的信息添加到文本浏览框中 */

240     textBrowser->append("已停止监听端口:"

241                         + spinBox->text());

242 }

243

244 /* 清除文本浏览框里的内容 */

245 void MainWindow::clearTextBrowser()

246 {

247     /* 清除文本浏览器的内容 */

248     textBrowser->clear();

249 }

250

251 /* 服务端接收消息 */

252 void MainWindow::receiveMessages()

253 {

254     /* 读取接收到的消息 */

255     QString messages = "客户端:" + tcpSocket->readAll();

256     textBrowser->append(messages);

257 }

258

259 /* 服务端发送消息 */

260 void MainWindow::sendMessages()

261 {

262     if(NULL == tcpSocket)

263         return;

264

265     /* 如果已经连接 */

266     if(tcpSocket->state() == tcpSocket->ConnectedState) {

267         /* 发送消息 */

268         tcpSocket->write(lineEdit->text().toUtf8().data());

269

270         /* 在服务端插入发送的消息 */

271         textBrowser->append("服务端:" + lineEdit->text());

272     }

273 }

274

275 /* 服务端状态改变 */

276 void MainWindow::socketStateChange(QAbstractSocket::SocketState state)

277 {

278     switch (state) {

279     case QAbstractSocket::UnconnectedState:

280         textBrowser->append("scoket状态:UnconnectedState");

281         break;

282     case QAbstractSocket::ConnectedState:

283         textBrowser->append("scoket状态:ConnectedState");

284         break;

285     case QAbstractSocket::ConnectingState:

286         textBrowser->append("scoket状态:ConnectingState");

287         break;

288     case QAbstractSocket::HostLookupState:

289         textBrowser->append("scoket状态:HostLookupState");

290         break;

291     case QAbstractSocket::ClosingState:

292         textBrowser->append("scoket状态:ClosingState");

293         break;

294     case QAbstractSocket::ListeningState:

295         textBrowser->append("scoket状态:ListeningState");

296         break;

297     case QAbstractSocket::BoundState:

298         textBrowser->append("scoket状态:BoundState");

299         break;

300     default:

301         break;

302     }

303 }

上面的代码主要是服务端开启监听,如果有客户端连到服务端,就会发射newConnection()信号,同时也连接到接收消息的信号与槽函数。点击发送消息按钮就可以使用tcpSocket发送消息。注意发送消息和接收消息都是通过tcpSocket的read()和write()进行。

未完待续....

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码