英雄联盟qt语音下载(英雄联盟qt语音连不上)

英雄联盟qt语音下载(英雄联盟qt语音连不上)

LOL自带有可能是你进页面的时候没打勾所有你进游戏选择区的时候注意一下右上有个开启QT内置语音打勾就好了!!

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

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

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

第十一章《网络编程》

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

11.3 UDP通信

11.3.1 UDP简介

UDP(User Datagram Protocol即用户数据报协议)是一个轻量级的,不可靠的,面向数据报的无连接协议。我们日常生活中使用的QQ,其聊天时的文字内容是使用UDP协议进行消息发送的。因为QQ有很多用户,发送的大部分都是短消息,要求能及时响应,并且对安全性要求不是很高的情况下使用UDP协议。但是QQ也并不是完全使用UDP协议,比如我们在传输文件时就会选择TCP协议,保证文件正确传输。像QQ语音和QQ视频通话,UDP的优势就很突出了。在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。

QUdpSocket类提供了一个UDP套接字。QUdpSocket是QAbstractSocket的子类,允许发送和接收UDP数据报。使用该类最常见的方法是使用bind()绑定到一个地址和端口,然后调用writeDatagram()和readDatagram() / receiveDatagram()来传输数据。注意发送数据一般少于512字节。如果发送多于512字节的数据,即使我们发送成功了,也会在IP层被分片(分成小片段)。

如果您想使用标准的QIODevice函数read()、readLine()、write()等,您必须首先通过调用connectToHost()将套接字直接连接到对等体。每次将数据报写入网络时,套接字都会发出bytesWritten()信号。

如果您只是想发送数据报,您不需要调用bind()。readyRead()信号在数据报到达时发出。在这种情况下,hasPendingDatagrams()返回true。调用pendingDatagramSize()来获取第一个待处理数据报的大小,并调用readDatagram()或receiveDatagram()来读取它。注意:当您接收到readyRead()信号时,一个传入的数据报应该被读取,否则这个信号将不会被发送到下一个数据报。

UDP通信示意图如下。重点是QUdpSocket类,已经为我们提供了UDP通信的基础。

UDP消息传送有三种模式,分别是单播、广播和组播三种模式。

单播(unicast):单播用于两个主机之间的端对端通信,需要知道对方的IP地址与端口。

广播(broadcast):广播UDP与单播UDP的区别就是IP地址不同,广播一般使用广播地址255.255.255.255,将消息发送到在同一广播(也就是局域网内同一网段)网络上的每个主机。值得强调的是:本地广播信息是不会被路由器转发。当然这是十分容易理解的,因为如果路由器转发了广播信息,那么势必会引起网络瘫痪。这也是为什么IP协议的设计者故意没有定义互联网范围的广播机制。广播地址通常用于在网络游戏中处于同一本地网络的玩家之间交流状态信息等。其实广播顾名思义,就是想局域网内所有的人说话,但是广播还是要指明接收者的端口号的,因为不可能接受者的所有端口都来收听广播。

组播(multicast):组播(多点广播),也称为“多播”,将网络中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。在广域网上广播的时候,其中的交换机和路由器只向需要获取数据的主机复制并转发数据。主机可以向路由器请求加入或退出某个组,网络中的路由器和交换机有选择地复制并传输数据,将数据仅仅传输给组内的主机。多播的这种功能,可以一次将数据发送到多个主机,又能保证不影响其他不需要(未加入组)的主机的其他通信。

注意:单播一样和多播是允许在广域网即Internet上进行传输的,而广播仅仅在同一局域网上才能进行。

11.3.2 UDP单播与广播

广播UDP与单播UDP的区别就是IP地址不同,所以我们的实例可以写成一个。我们可以这么理解,单播实际上是通信上对应一对一,广播则是一对多(多,这里指广播地址内的所有主机)。

11.3.2.1应用实例

本例目的:了解QUdpSocket单播和广播使用。

例10_udp_unicast_broadcast,UDP单播与广播应用(难度:一般)。项目路径为Qt/2/10_udp_unicast_broadcast。本例大体流程首先获取本地IP地址。创建一个udpSocket套接字,然后绑定本地主机的端口(也就是监听端口)。我们可以使用QUdpSocket类提供的读写函数readDatagram和writeDatagram,知道目标IP地址和端口,即可完成消息的接收与发送。

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

10_udp_unicast_broadcast.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  10_udp_unicast_broadcast

  * @brief     mainwindow.h

  * @author    Deng Zhimao

  * @email     1252699831@qq.com

  * @net      www.openedv.com

  * @date      2021-04-14

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

1  #ifndef MAINWINDOW_H

2  #define MAINWINDOW_H

3 

4  #include <QMainWindow>

5  #include <QUdpSocket>

6  #include <QVBoxLayout>

7  #include <QHBoxLayout>

8  #include <QPushButton>

9  #include <QTextBrowser>

10 #include <QLabel>

11 #include <QComboBox>

12 #include <QSpinBox>

13 #include <QHostInfo>

14 #include <QLineEdit>

15 #include <QNetworkInterface>

16 #include <QDebug>

17

18 class MainWindow : public QMainWindow

19 {

20   Q_OBJECT

21

22 public:

23   MainWindow(QWidget *parent = nullptr);

24   ~MainWindow();

25

26 private:

27   /* Udp通信套接字 */

28   QUdpSocket *udpSocket;

29

30   /* 按钮 */

31   QPushButton *pushButton[5];

32

33   /* 标签文本 */

34   QLabel *label[3];

35

36   /* 水平容器 */

37   QWidget *hWidget[3];

38

39   /* 水平布局 */

40   QHBoxLayout *hBoxLayout[3];

41

42   /* 垂直容器 */

43   QWidget *vWidget;

44

45   /* 垂直布局 */

46   QVBoxLayout *vBoxLayout;

47

48   /* 文本浏览框 */

49   QTextBrowser *textBrowser;

50

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

52   QComboBox *comboBox;

53

54   /* 用于选择端口 */

55   QSpinBox *spinBox[2];

56

57   /* 文本输入框 */

58   QLineEdit *lineEdit;

59

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

61   QList<QHostAddress> IPlist;

62

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

64   void getLocalHostIP();

65

66 private slots:

67   /* 绑定端口 */

68   void bindPort();

69

70   /* 解绑端口 */

71   void unbindPort();

72

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

74   void clearTextBrowser();

75

76   /* 接收到消息 */

77   void receiveMessages();

78

79   /* 发送消息 */

80   void sendMessages();

81

82   /* 广播消息 */

83   void sendBroadcastMessages();

84

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

86   void socketStateChange(QAbstractSocket::SocketState);

87 };

88 #endif // MAINWINDOW_H

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

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

mainwindow.cpp编程后的代码

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

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

  * @projectName  10_udp_unicast_broadcast

  * @brief     mainwindow.cpp

  * @author    Deng Zhimao

  * @email     1252699831@qq.com

  * @net      www.openedv.com

  * @date      2021-04-14

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

1  #include "mainwindow.h"

2 

3  MainWindow::MainWindow(QWidget *parent)

4    : QMainWindow(parent)

5  {

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

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

8 

9    /* udp套接字 */

10   udpSocket = new QUdpSocket(this);

11 

12   /* 绑定端口按钮 */

13   pushButton[0] = new QPushButton();

14   /* 解绑端口按钮 */

15   pushButton[1] = new QPushButton();

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

17   pushButton[2] = new QPushButton();

18   /* 发送消息按钮 */

19   pushButton[3] = new QPushButton();

20   /* 广播消息按钮 */

21   pushButton[4] = new QPushButton();

22 

23   /* 水平布局一 */

24   hBoxLayout[0] = new QHBoxLayout();

25   /* 水平布局二 */

26   hBoxLayout[1] = new QHBoxLayout();

27   /* 水平布局三 */

28   hBoxLayout[2] = new QHBoxLayout();

29   /* 水平布局四 */

30   hBoxLayout[3] = new QHBoxLayout();

31 

32   /* 水平容器一 */

33   hWidget[0] = new QWidget();

34   /* 水平容器二 */

35   hWidget[1] = new QWidget();

36   /* 水平容器三 */

37   hWidget[2] = new QWidget();

38 

39 

40   vWidget = new QWidget();

41   vBoxLayout = new QVBoxLayout();

42 

43   /* 标签实例化 */

44   label[0] = new QLabel();

45   label[1] = new QLabel();

46   label[2] = new QLabel();

47 

48   lineEdit = new QLineEdit();

49   comboBox = new QComboBox();

50   spinBox[0] = new QSpinBox();

51   spinBox[1] = new QSpinBox();

52   textBrowser = new QTextBrowser();

53 

54   label[0]->setText("目标IP地址:");

55   label[1]->setText("目标端口:");

56   label[2]->setText("绑定端口:");

57 

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

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

60               QSizePolicy::Fixed);

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

62               QSizePolicy::Fixed);

63   label[2]->setSizePolicy(QSizePolicy::Fixed,

64               QSizePolicy::Fixed);

65 

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

67   spinBox[0]->setRange(10000, 99999);

68   spinBox[1]->setRange(10000, 99999);

69 

70   pushButton[0]->setText("绑定端口");

71   pushButton[1]->setText("解除绑定");

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

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

74   pushButton[4]->setText("广播消息");

75 

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

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

78 

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

80   lineEdit->setText("您好!");

81 

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

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

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

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

86 

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

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

89 

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

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

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

93   hBoxLayout[1]->addWidget(spinBox[0]);

94   hBoxLayout[1]->addWidget(label[2]);

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

96 

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

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

99 

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

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

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

103   hBoxLayout[2]->addWidget(pushButton[4]);

104

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

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

107

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

109   vBoxLayout->addWidget(textBrowser);

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

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

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

113

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

115   vWidget->setLayout(vBoxLayout);

116

117   /* 居中显示 */

118   setCentralWidget(vWidget);

119

120   /* 获取本地ip */

121   getLocalHostIP();

122

123   /* 信号槽连接 */

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

125       this, SLOT(bindPort()));

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

127       this, SLOT(unbindPort()));

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

129       this, SLOT(clearTextBrowser()));

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

131       this, SLOT(sendMessages()));

132   connect(pushButton[4], SIGNAL(clicked()),

133       this, SLOT(sendBroadcastMessages()));

134   connect(udpSocket, SIGNAL(readyRead()),

135       this, SLOT(receiveMessages()));

136   connect(udpSocket,

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

138       this,

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

140 }

141

142 MainWindow::~MainWindow()

143 {

144 }

145

146 void MainWindow::bindPort()

147 {

148   quint16 port = spinBox[0]->value();

149

150   /* 绑定端口需要在socket的状态为UnconnectedState */

151   if (udpSocket->state() != QAbstractSocket::UnconnectedState)

152     udpSocket->close();

153

154   if (udpSocket->bind(port)) {

155     textBrowser->append("已经成功绑定端口:"

156               + QString::number(port));

157

158     /* 设置界面中的元素的可用状态 */

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

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

161     spinBox[1]->setEnabled(false);

162   }

163 }

164

165 void MainWindow::unbindPort()

166 {

167   /* 解绑,不再监听 */

168   udpSocket->abort();

169

170   /* 设置界面中的元素的可用状态 */

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

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

173   spinBox[1]->setEnabled(true);

174 }

175

176 /* 获取本地IP */

177 void MainWindow::getLocalHostIP()

178 {

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

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

181

182   // /* 主机的信息 */

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

184

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

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

187   // IPlist = hostInfo.addresses();

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

189

190   // /* 遍历IPlist */

191   // foreach (QHostAddress ip, IPlist) {

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

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

194   //  }

195

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

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

198   QList<QNetworkInterface> list

199       = QNetworkInterface::allInterfaces();

200

201   /* 遍历list */

202   foreach (QNetworkInterface interface, list) {

203

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

205     QList<QNetworkAddressEntry> entryList

206         = interface.addressEntries();

207

208     /* 遍历entryList */

209     foreach (QNetworkAddressEntry entry, entryList) {

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

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

212           QAbstractSocket::IPv4Protocol) {

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

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

215         IPlist<<entry.ip();

216       }

217     }

218   }

219 }

220

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

222 void MainWindow::clearTextBrowser()

223 {

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

225   textBrowser->clear();

226 }

227

228 /* 客户端接收消息 */

229 void MainWindow::receiveMessages()

230 {

231   /* 局部变量,用于获取发送者的IP和端口 */

232   QHostAddress peerAddr;

233   quint16 peerPort;

234

235   /* 如果有数据已经准备好 */

236   while (udpSocket->hasPendingDatagrams()) {

237     /* udpSocket发送的数据报是QByteArray类型的字节数组 */

238     QByteArray datagram;

239

240     /* 重新定义数组的大小 */

241     datagram.resize(udpSocket->pendingDatagramSize());

242

243     /* 读取数据,并获取发送方的IP地址和端口 */

244     udpSocket->readDatagram(datagram.data(),

245                 datagram.size(),

246                 &peerAddr,

247                 &peerPort);

248     /* 转为字符串 */

249     QString str = datagram.data();

250

251     /* 显示信息到文本浏览框窗口 */

252     textBrowser->append("接收来自"

253               + peerAddr.toString()

254               + ":"

255               + QString::number(peerPort)

256               + str);

257   }

258 }

259

260 /* 客户端发送消息 */

261 void MainWindow::sendMessages()

262 {

263   /* 文本浏览框显示发送的信息 */

264   textBrowser->append("发送:" + lineEdit->text());

265

266   /* 要发送的信息,转为QByteArray类型字节数组,数据一般少于512个字节 */

267   QByteArray data = lineEdit->text().toUtf8();

268

269   /* 要发送的目标Ip地址 */

270   QHostAddress peerAddr = IPlist[comboBox->currentIndex()];

271

272   /* 要发送的目标端口号 */

273   quint16 peerPort = spinBox[1]->value();

274

275   /* 发送消息 */

276   udpSocket->writeDatagram(data, peerAddr, peerPort);

277 }

278

279 void MainWindow::sendBroadcastMessages()

280 {

281   /* 文本浏览框显示发送的信息 */

282   textBrowser->append("发送:" + lineEdit->text());

283

284   /* 要发送的信息,转为QByteArray类型字节数组,数据一般少于512个字节 */

285   QByteArray data = lineEdit->text().toUtf8();

286

287   /* 广播地址,一般为255.255.255.255,

288   * 同一网段内监听目标端口的程序都会接收到消息 */

289   QHostAddress peerAddr = QHostAddress::Broadcast;

290

291   /* 要发送的目标端口号 */

292   quint16 peerPort = spinBox[1]->text().toInt();

293

294   /* 发送消息 */

295   udpSocket->writeDatagram(data, peerAddr, peerPort);

296 }

297 /* socket状态改变 */

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

299 {

300   switch (state) {

301   case QAbstractSocket::UnconnectedState:

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

303     break;

304   case QAbstractSocket::ConnectedState:

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

306     break;

307   case QAbstractSocket::ConnectingState:

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

309     break;

310   case QAbstractSocket::HostLookupState:

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

312     break;

313   case QAbstractSocket::ClosingState:

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

315     break;

316   case QAbstractSocket::ListeningState:

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

318     break;

319   case QAbstractSocket::BoundState:

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

321     break;

322   default:

323     break;

324   }

325 }

第146~163行,绑定端口。使用bind方法,即可绑定一个端口。注意我们绑定的端口不能和主机已经使用的端口冲突!

第165~174行,解绑端口。使用abort方法即可解绑。

第229~258行,接收消息,注意接收消息是QByteArray字节数组。读数组使用的是readDatagram方法,在readDatagram方法里可以获取对方的套接字IP地址与端口号。

第261~277行,单播消息,需要知道目标IP与目标端口号。即可用writeDatagram方法发送消息。

第279~296行,广播消息与单播消息不同的是将目标IP地址换成了广播地址,一般广播地址为255.255.255.255。

11.3.2.2程序运行效果

本实例可以做即是发送者,也是接收者。如果在同一台主机同一个系统里运行两个本例程序。不能绑定同一个端口!否则会冲突!当您想测试在同一局域网内不同主机上运行此程序,那么绑定的端口号可以相同。

本例设置目标IP地址为127.0.0.1,此IP地址是Ubuntu/Windows上的环回IP地址,可以用于无网络时测试。绑定端口号与目标端口号相同,也就是说,此程序正在监听端口号为10000的数据,此程序也向目标IP地址127.0.0.1的10000端口号发送数据,实际上此程序就完成了自发自收。

当我们点击发送消息按钮时,文本消息窗口显示发送的数据“您好!”,同时接收到由本地IP 127.0.0.1发出的数据“您好!”。其中ffff:是通信套接字的标识。呵呵!您可能会问为什么不是本主机的其它地址如(192.168.1.x)发出的呢?因为我们选择了目标的IP地址为127.0.0.1,那么要与此目标地址通信,必须使用相同网段的IP设备与之通信。注意不能用本地环回发送消息到其他主机上。因为本地环回IP只适用于本地主机上的IP通信。

当我们点击广播消息按钮时,广播发送的目标IP地址变成了广播地址255.255.255.255。那么我们将收到从本地IP地址192.168.x.x的数据。如下图,收到了从192.168.1.129发送过来的数据。因为环回IP 127.0.0.1的广播地址为255.0.0.0,所以要与255.255.255.255的网段里的IP通信数据必须是由192.168.x.x上发出的。如果其他同一网段上的其他主机正在监听目标端口,那么它们将同时收到消息。这也验证了上一小节为什么会从127.0.0.1发送数据。

本例不难,可能有点绕,大家多参考资料理解理解,知识点有点多,如果没有些通信基础的话,我们需要慢慢吃透。

未完待续....

英雄联盟QT语音需要在登录的时候勾选,进入游戏就能开启了,下面是具体步骤:首先是进入到游戏中,在选取游戏大区前,注意查看右上角 将QT语音前面的钩子勾上,即可开启语音功能。

试着把登录界面的开启QT内置语音打开看行不行

(0)

相关推荐