Hi,今天用一个小例子,陈述一下 Qt 里使用 TCP 通讯的流程 。
代码链接:
https://doc.qt.io/qt-5/examples.NETwork.html运行效果:

文章插图
Server 端运行效果:

文章插图
显示 IP + 端口,然后静静地的等待客户端的连接 。
源码文件:
msg_server/├── msg_server.pro├── main.cpp├── server.cpp└── server.h源码分析如下 。创建 TCP Server在构造函数中进行初始化:
// server.cppServer::Server(QWidget *parent): QDialog(parent), statusLabel(new QLabel){// 建立 TCP Server,并监听tcpServer = new QTcpServer(this);tcpServer->listen()// 获取 Server 的 IP 地址,并用其初始化 UI[...]// 一旦有 TCP 连接,则调用 sendMsg() 发送数据给客户端connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendMsg);}要点:1、QTcpServer 是对 TCP-based server 的封装 。
2、QTcpServer::listen() 用于监听是否有客户端发起连接 。
3、一旦有客户端访问,QTcpServer 会发出 newConnection() 信号,我们通过绑定槽函数 sendMsg() 以实现发送消息的功能 。
获取 Server IP在界面上显示服务端的 IP 信息:
// server.cppServer::Server(QWidget *parent): QDialog(parent), statusLabel(new QLabel){// 创建 TCP Server[...]QString ipAddress;// 获得所有的 IP 地址QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();// 解析出第一个可用的 IPv4 地址for (int i = 0; i < ipAddressesList.size(); ++i) {if (ipAddressesList.at(i) != QHostAddress::LocalHost &&ipAddressesList.at(i).toIPv4Address()) {ipAddress = ipAddressesList.at(i).toString();break;}}// 初始化 UI[...]}要点:1、QNetworkInterface 是对网络接口 (例如 lo、eth0...) 的封装 。
2、QNetworkInterface::allAddresses() 会返回系统里所有的 IP 地址 。
3、QHostAddress 是对 IP 地址(IPv4、IPv6) 的封装 。
4、QHostAddress::toIPv4Address() 会将点分式的 IPv4 地址转换为数字式,例如 127.0.0.1 会被转换为 0x7F000001,失败则返回 0 。
给客户端发送消息当有客户端连接到来时,槽函数 sendMsg()会被调用 :
// server.cppvoid Server::sendMsg(){// Prepare messageQByteArray block;QDataStream out(&block, QIODevice::WriteOnly);out << message[QRandomGenerator::global()->bounded(message.size())];// Get pending connectionQTcpSocket *clientConnection = tcpServer->nextPendingConnection();connect(clientConnection, &QAbstractSocket::disconnected,clientConnection, &QObject::deleteLater);// Send messageclientConnection->write(block);clientConnection->disconnectFromHost();}要点:1、QTcpSocket 是对 TCP Socket 的封装 。
2、为了与主机无关 (字节序等),这里选用 QByteArray 以二进制的格式来存储数据 。使用 QDataStream 可以轻松地将 Message 写到 QByteArray 里 。
3、QDataStream 从各种 IO 设备 (QIODeice 的子类),例如 QByteArray、文件 (QFile) 等读写二进制数据 。
4、从 QTcpServer::nextPendingConnection() 获得客户端的 Socket 。
5、用 QTcpSocket::write() 将 Message 通过网络发给客户端 。
6、最后,通过 QTcpSocket::disconnectFromHost 断开连接,它会等待直到数据成功被写出去 。
Client 端运行效果:

文章插图
每次点击 "Get Message" 按钮,客户端都会从服务端随机获取到一条问候信息 。
源码文件:
msg_client/├── msg_client.pro├── client.cpp├── client.h└── main.cpp创建 TCP Socket// client.cppClient::Client(QWidget *parent): QDialog(parent), hostCombo(new QComboBox), portLineEdit(new QLineEdit), statusLabel(new QLabel(tr("This examples requires that you run then Message Server example as well."))), getMsgButton(new QPushButton(tr("Get Message"))), tcpSocket(new QTcpSocket(this)){// Init UI[...]// Setup QDataStream's sourcein.setDevice(tcpSocket);in.setVersion(QDataStream::Qt_5_10);// Setup signal & slotconnect(getMsgButton, &QAbstractButton::clicked,this, &Client::requestNewMsg);connect(tcpSocket, &QIODevice::readyRead, this, &Client::readMsg);}要点:1、用 QTcpSocket 创建 TCP Socket 。
2、将 QDataStream 数据流的输入源设置为 Socket 。
3、设置信号槽:当 Socket 有数据时,调用 readMsg() 将其读走 。
从服务端读取消息当用户点击 "Get Message" 按钮时,requestNewMsg() 会被调用
推荐阅读
- 跟单员的职责是什么你都了解吗? 跟单员是做什么的
- 事业单位|了解企业岗位工作实际要求,才能更好地适应职场
- 边际效用的生活例子 心理边际效应
- 你对神兽了解多少? 神兽是什么意思
- 洗面奶|运动减肥时,体重却降不下来,或与这5个因素有关,需了解
- 食用注意事项要了解 生蚝怎么清洗内脏图解
- 餐后一小时血糖高怎么办?
- 你了解IPO是什么吗 ipo是什么意思呢
- 古典|热血传奇:三职业详解!传奇三职业的特色和介绍你真的了解吗?
- 每天散步一小时的好处
