跟着例子学Qt--1.blockingfortuneclient
来源:互联网 发布:淘宝卖家买家秀对比 编辑:程序博客网 时间:2024/05/29 18:38
教训
之前这篇博文早已写好,不知道是忘记发布还是其他原因,写新博客时默认打开了该博客,但是没有留意直接删除内容开写,写完发布着例子学Qt2后发现跟着例子学Qt少了1~ 额,悲剧…
概述
这个例子的重点告诉我们如何利用QThread来调用系统的同步接口,Qt帮助中也提出千万不要再主线程中干同样的事,因为这将导致主线程卡死。
服务器端fortuneserver
上核心代码
tcpServer = new QTcpServer(this); if (!tcpServer->listen()) { // 监听随机端口(可通过tcpServer->serverPort()获取),任意ip QMessageBox::critical(this, tr("Fortune Server"), tr("Unable to start the server: %1.") .arg(tcpServer->errorString())); close(); return; }//! [0] QString ipAddress; QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); // use the first non-localhost IPv4 address for (int i = 0; i < ipAddressesList.size(); ++i) { if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) { ipAddress = ipAddressesList.at(i).toString(); break; } } // if we did not find one, use IPv4 localhost if (ipAddress.isEmpty()) ipAddress = QHostAddress(QHostAddress::LocalHost).toString(); // 通过以上方式查找到本机ip statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n" "Run the Fortune Client example now.") .arg(ipAddress).arg(tcpServer->serverPort()));
剩下的就是响应客户端连接的代码,连接信号和槽connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune);
,处理函数如下:
void Server::sendFortune(){//! [5] QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_0); // 为了各种版本的兼容最好设置版本号 out << fortunes.at(qrand() % fortunes.size());//! [4] //! [7] QTcpSocket *clientConnection = tcpServer->nextPendingConnection(); connect(clientConnection, &QAbstractSocket::disconnected, clientConnection, &QObject::deleteLater);//! [7] //! [8] clientConnection->write(block); // 发送一段文字后随即关闭连接。 clientConnection->disconnectFromHost();//! [5]}
客户端blockingfortuneclient
重点在于FortuneThread中,完整分析cpp文件:
FortuneThread::FortuneThread(QObject *parent) : QThread(parent), quit(false){}//! [0]FortuneThread::~FortuneThread(){ mutex.lock(); quit = true; cond.wakeOne(); // 主要需要唤醒下当前线程 mutex.unlock(); wait(); // 如果不wait可能导致FortuneThread已经析构,而run还为结束,最后可能在run中由于访问FortuneThread已经析构的成员而导致崩溃等现象。}//! [0]//! [1] //! [2]void FortuneThread::requestNewFortune(const QString &hostName, quint16 port) // 连接服务器{//! [1] QMutexLocker locker(&mutex); // 注意加锁 this->hostName = hostName; this->port = port;//! [3] if (!isRunning()) start(); else cond.wakeOne();}//! [2] //! [3]//! [4]void FortuneThread::run(){ mutex.lock(); // 由于下面获取hostName和port,这两个参数也可能在主线程改变(requestNewFortune)故需要加锁//! [4] //! [5] QString serverName = hostName; quint16 serverPort = port; mutex.unlock();//! [5]//! [6] while (!quit) {//! [7] const int Timeout = 5 * 1000; QTcpSocket socket; socket.connectToHost(serverName, serverPort);//! [6] //! [8] if (!socket.waitForConnected(Timeout)) { // 阻塞等待连接成功 emit error(socket.error(), socket.errorString()); return; }//! [8] //! [11] QDataStream in(&socket); in.setVersion(QDataStream::Qt_4_0); // 同样设置了版本号 QString fortune;//! [11] //! [12] do { if (!socket.waitForReadyRead(Timeout)) { emit error(socket.error(), socket.errorString()); return; } in.startTransaction(); in >> fortune; } while (!in.commitTransaction()); // 这里通过commitTransaction可以判断发送是否发生异常,这个值得借鉴//! [12] //! [15] mutex.lock(); emit newFortune(fortune);//! [7] cond.wait(&mutex); // 接收一次消息后阻塞等待条件 serverName = hostName; // 下次仍然重设hostName及port serverPort = port; mutex.unlock(); }//! [15]}
这里通过QThread代表了连接QTcpSocket等的连接,均采用同步方式,可以比较清晰地知道当前QTcpSocket的状态,比较容易管理。后面分析异步方式使用时将进行对比~
0 0
- 跟着例子学Qt--1.blockingfortuneclient
- 跟着例子学Qt--2.standalone( C++ QWebChannel server and a HTML/JS client)
- 跟着vivi学bootloader
- 跟着学制表
- 跟着示例学Oozie
- 跟着示例学Oozie
- 跟着示例学Oozie
- 【跟着stackoverflow学Pandas】
- 【跟着stackoverflow学Pandas】
- 跟着示例学Oozie
- 跟着jdk学奇技淫巧~
- 跟着教练学打球 1
- 跟着教练学打球 2
- 跟着教练学打球 3
- 跟着教练学打球 4
- 跟着教练学打球 5
- 跟着教练学打球 6
- 跟着cc学设计模式
- 组件化架构剖析
- 数据结构-直接插入排序与希尔排序
- iO文件路径问题
- JAVA 常用GUI工具包
- 【并发编程】系统架构和组件详解
- 跟着例子学Qt--1.blockingfortuneclient
- mysql 优化(一)
- Codeforces Round #403 (Div. 2) C. Andryusha and Colored Balloons
- HRBUST1313-火影忍者之~静音
- 各种字符编码方式详解及由来(ANSI,UNICODE,UTF-8,GB2312,GBK)
- js-自定义属性
- C++第1次上机报告—循环程序设计
- PAT--1126. Eulerian Path
- sqlhelper重构