Qt文档阅读笔记-Simple Chat Example解析

x33g5p2x  于2022-06-06 转载在 其他  
字(6.2k)|赞(0)|评价(0)|浏览(623)

这个实例使用QWebSocket和QWebSocketServer去构造WebSocket协议的极简聊天室。

官方对于这个实例给出的文档方面的介绍就这么多,下面是对应的代码,我自己补充下:

文件一共如下:

我们由简入深分析下,首先是simplechat.pro

  1. QT = websockets
  2. TARGET = chatserver
  3. CONFIG += console
  4. CONFIG -= app_bundle
  5. TEMPLATE = app
  6. SOURCES += \
  7. main.cpp \
  8. chatserver.cpp
  9. HEADERS += \
  10. chatserver.h
  11. EXAMPLE_FILES += chatclient.html
  12. target.path = $$[QT_INSTALL_EXAMPLES]/websockets/simplechat
  13. INSTALLS += target

这里主要是包含websockets模块,使用的语法是 QT = websockets

main.cpp就是实例化ChatServer在此不再说明。

下面是chartserver.h和chartserver.cpp

  1. #ifndef CHATSERVER_H
  2. #define CHATSERVER_H
  3. #include <QtCore/QObject>
  4. #include <QtCore/QList>
  5. QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
  6. QT_FORWARD_DECLARE_CLASS(QWebSocket)
  7. QT_FORWARD_DECLARE_CLASS(QString)
  8. class ChatServer : public QObject
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit ChatServer(quint16 port, QObject *parent = nullptr);
  13. ~ChatServer() override;
  14. private slots:
  15. void onNewConnection();
  16. void processMessage(const QString &message);
  17. void socketDisconnected();
  18. private:
  19. QWebSocketServer *m_pWebSocketServer;
  20. QList<QWebSocket *> m_clients;
  21. };
  22. #endif //CHATSERVER_H
  1. #include "chatserver.h"
  2. #include <QtWebSockets>
  3. #include <QtCore>
  4. #include <cstdio>
  5. using namespace std;
  6. QT_USE_NAMESPACE
  7. static QString getIdentifier(QWebSocket *peer)
  8. {
  9. return QStringLiteral("%1:%2").arg(peer->peerAddress().toString(),
  10. QString::number(peer->peerPort()));
  11. }
  12. //! [constructor]
  13. ChatServer::ChatServer(quint16 port, QObject *parent) :
  14. QObject(parent),
  15. m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Chat Server"),
  16. QWebSocketServer::NonSecureMode,
  17. this))
  18. {
  19. if (m_pWebSocketServer->listen(QHostAddress::Any, port))
  20. {
  21. QTextStream(stdout) << "Chat Server listening on port " << port << '\n';
  22. connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
  23. this, &ChatServer::onNewConnection);
  24. }
  25. }
  26. ChatServer::~ChatServer()
  27. {
  28. m_pWebSocketServer->close();
  29. }
  30. //! [constructor]
  31. //! [onNewConnection]
  32. void ChatServer::onNewConnection()
  33. {
  34. auto pSocket = m_pWebSocketServer->nextPendingConnection();
  35. QTextStream(stdout) << getIdentifier(pSocket) << " connected!\n";
  36. pSocket->setParent(this);
  37. connect(pSocket, &QWebSocket::textMessageReceived,
  38. this, &ChatServer::processMessage);
  39. connect(pSocket, &QWebSocket::disconnected,
  40. this, &ChatServer::socketDisconnected);
  41. m_clients << pSocket;
  42. }
  43. //! [onNewConnection]
  44. //! [processMessage]
  45. void ChatServer::processMessage(const QString &message)
  46. {
  47. QWebSocket *pSender = qobject_cast<QWebSocket *>(sender());
  48. for (QWebSocket *pClient : qAsConst(m_clients)) {
  49. if (pClient != pSender) //don't echo message back to sender
  50. pClient->sendTextMessage(message);
  51. }
  52. }
  53. //! [processMessage]
  54. //! [socketDisconnected]
  55. void ChatServer::socketDisconnected()
  56. {
  57. QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
  58. QTextStream(stdout) << getIdentifier(pClient) << " disconnected!\n";
  59. if (pClient)
  60. {
  61. m_clients.removeAll(pClient);
  62. pClient->deleteLater();
  63. }
  64. }
  65. //! [socketDisconnected]

这里解释几个点:

①m_pWebSocketServer是QWebSocketServer,指定其名和mode以及开通的端口号;

②newConnection中,使用m_pWebSocketServer获取nextPendingConnection,然后得到这个与客户端相连的socket后,设置信号与槽。

③processMessage,将获取到用户发来的信号与槽,发送给所有连接到服务器的用户。

④socketDisconnect,当用户断开连接后,把其用户移除m_clients。

下面是chartclient.html

  1. <html>
  2. <head>
  3. <title>WebSocket Chat Client</title>
  4. </head>
  5. <body>
  6. <h1>WebSocket Chat Client</h1>
  7. <p>
  8. Host: <input id="webSocketHost" type="text" value="localhost:1234"/>
  9. </p>
  10. <p>
  11. <button onClick="initWebSocket();">Connect</button>
  12. <button id="disconnectButton" onClick="stopWebSocket();" disabled>Disconnect</button>
  13. <button onClick="checkSocket();">State</button>
  14. </p>
  15. <p>
  16. <textarea id="debugTextArea" style="width:400px;height:200px;" readonly></textarea>
  17. </p>
  18. <p>
  19. <input type="text" id="inputNick" value="nickname" />
  20. <input type="text" id="inputText" onkeydown="if(event.keyCode==13)sendMessage();"/>
  21. <button id="sendButton" onClick="sendMessage();" disabled>Send</button>
  22. </p>
  23. <script type="text/javascript">
  24. var debugTextArea = document.getElementById("debugTextArea");
  25. function debug(message) {
  26. debugTextArea.value += message + "\n";
  27. debugTextArea.scrollTop = debugTextArea.scrollHeight;
  28. }
  29. function sendMessage() {
  30. var nickname = document.getElementById("inputNick").value;
  31. var msg = document.getElementById("inputText").value;
  32. var strToSend = nickname + ": " + msg;
  33. if ( websocket != null )
  34. {
  35. document.getElementById("inputText").value = "";
  36. websocket.send( strToSend );
  37. console.log( "string sent :", '"'+strToSend+'"' );
  38. debug(strToSend);
  39. }
  40. }
  41. var websocket = null;
  42. function initWebSocket() {
  43. try {
  44. if (typeof MozWebSocket == 'function')
  45. WebSocket = MozWebSocket;
  46. if ( websocket && websocket.readyState == 1 )
  47. websocket.close();
  48. var wsUri = "ws://" + document.getElementById("webSocketHost").value;
  49. websocket = new WebSocket( wsUri );
  50. websocket.onopen = function (evt) {
  51. debug("CONNECTED");
  52. document.getElementById("disconnectButton").disabled = false;
  53. document.getElementById("sendButton").disabled = false;
  54. };
  55. websocket.onclose = function (evt) {
  56. debug("DISCONNECTED");
  57. document.getElementById("disconnectButton").disabled = true;
  58. document.getElementById("sendButton").disabled = true;
  59. };
  60. websocket.onmessage = function (evt) {
  61. console.log( "Message received :", evt.data );
  62. debug( evt.data );
  63. };
  64. websocket.onerror = function (evt) {
  65. debug('ERROR: ' + evt.data);
  66. };
  67. } catch (exception) {
  68. debug('ERROR: ' + exception);
  69. }
  70. }
  71. function stopWebSocket() {
  72. if (websocket)
  73. websocket.close();
  74. }
  75. function checkSocket() {
  76. if (websocket != null) {
  77. var stateStr;
  78. switch (websocket.readyState) {
  79. case 0: {
  80. stateStr = "CONNECTING";
  81. break;
  82. }
  83. case 1: {
  84. stateStr = "OPEN";
  85. break;
  86. }
  87. case 2: {
  88. stateStr = "CLOSING";
  89. break;
  90. }
  91. case 3: {
  92. stateStr = "CLOSED";
  93. break;
  94. }
  95. default: {
  96. stateStr = "UNKNOW";
  97. break;
  98. }
  99. }
  100. debug("WebSocket state = " + websocket.readyState + " ( " + stateStr + " )");
  101. } else {
  102. debug("WebSocket is null");
  103. }
  104. }
  105. </script>
  106. </body>
  107. </html>

这个html代码,浏览器运行后,会创建一个websocket连接到服务端上,然后进行文本串的交互。

相关文章