网站首页 > 编程文章 正文
今日头条/西瓜视频/抖音短视频 同名:正点原子
原子哥今日头条/西瓜视频/抖音短视频账号:正点原子-原子哥
感谢各位的关注和支持,你们的关注和支持是正点原子无限前进的动力。
第十一章《网络编程》
由于本章内容较多,所以第十一章《网络编程》将会分为几个部分进行内容的发布,更多文章内容请持续关注今日头条正点原子官方账号。
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()进行。
未完待续....
猜你喜欢
- 2024-10-14 「Qt入门第31篇」 网络(一)Qt网络编程简介
- 2024-10-14 qt 做手机android的串口通讯 qt下串口通信
- 2024-10-14 Qt 读写txt文本文件(qt读入文件)
- 2024-10-14 Qt 信号槽连接不成功问题原因汇总
- 2024-10-14 QML 性能优化建议(一)(qml例程)
- 2024-10-14 C++ QT中文件的读写操作(UI界面)(qt怎么读取文件内容)
- 2024-10-14 Qt 中的智能指针(qt 函数指针)
- 2024-10-14 Qt如何读取和写入配置文件的数据(qt 读写配置文件)
- 2024-10-14 Qt pro文件中的常用宏说明(qt pro 自定义宏)
- 2024-10-14 Qt应用程序主窗口:拖放操作与打印文档
你 发表评论:
欢迎- 05-09Spring Boot3 RESTful 接口参数校验,这篇吃透就够了!
- 05-09《Spring6》第02节:基于XML方式搭建Spring6框架开发环境
- 05-09MapStruct架构设计(mapstruct @mapping)
- 05-09分布式微服务架构组件(分布式微服务架构设计)
- 05-09Java Swing组件下的JButton实例(java swing 组件)
- 05-09java基础都在这了,小主们拿去吧(java基础是指什么)
- 05-09AOP的实现落地(拦截过滤),一切都要从Servlet说起
- 05-09【Spring Boot】WebSocket 的 6 种集成方式
- 最近发表
-
- Spring Boot3 RESTful 接口参数校验,这篇吃透就够了!
- 《Spring6》第02节:基于XML方式搭建Spring6框架开发环境
- MapStruct架构设计(mapstruct @mapping)
- 分布式微服务架构组件(分布式微服务架构设计)
- Java Swing组件下的JButton实例(java swing 组件)
- java基础都在这了,小主们拿去吧(java基础是指什么)
- AOP的实现落地(拦截过滤),一切都要从Servlet说起
- 【Spring Boot】WebSocket 的 6 种集成方式
- Java 中五种最常见加密算法:原理、应用与代码实现
- 用注解进行参数校验,spring validation介绍、使用、实现原理分析
- 标签列表
-
- spire.doc (59)
- system.data.oracleclient (61)
- 按键小精灵源码提取 (66)
- pyqt5designer教程 (65)
- 联想刷bios工具 (66)
- c#源码 (64)
- graphics.h头文件 (62)
- mysqldump下载 (66)
- sqljdbc4.jar下载 (56)
- libmp3lame (60)
- maven3.3.9 (63)
- 二调符号库 (57)
- 苹果ios字体下载 (56)
- git.exe下载 (68)
- diskgenius_winpe (72)
- pythoncrc16 (57)
- solidworks宏文件下载 (59)
- qt帮助文档中文版 (73)
- satacontroller (66)
- hgcad (64)
- bootimg.exe (69)
- android-gif-drawable (62)
- axure9元件库免费下载 (57)
- libmysqlclient.so.18 (58)
- springbootdemo (64)
本文暂时没有评论,来添加一个吧(●'◡'●)