大连网站建设学校,数码港 太原网站开发公司,企业宣传册模板免费下载,.net网站空间一.WebSocket 介绍
1.概述
WebSocket 是一种在单个 TCP 连接上进行全双工通讯的协议#xff0c;它在 2011 年被 IETF 定为标准 RFC 6455#xff0c;并由 RFC7936 补充规范。与传统的 HTTP 协议不同#xff0c;WebSocket 允许服务器和客户端之间进行实时、双向的数据传输它在 2011 年被 IETF 定为标准 RFC 6455并由 RFC7936 补充规范。与传统的 HTTP 协议不同WebSocket 允许服务器和客户端之间进行实时、双向的数据传输打破了 HTTP 协议请求 - 响应的模式限制大大提高了数据传输的效率和实时性。 2.特点
全双工通信服务器和客户端可以在任意时刻向对方发送数据无需等待对方的请求。
实时性强由于采用了全双工通信数据可以即时传输非常适合实时性要求较高的应用场景如在线聊天、实时数据监控等。
较少的开销WebSocket 握手阶段使用 HTTP 协议建立连接后数据传输不再需要像 HTTP 那样携带大量的头部信息减少了数据传输的开销。
跨域支持WebSocket 支持跨域通信方便不同域名之间的服务器和客户端进行数据交互。 客户端与服务器交互图 3.应用场景
实时聊天应用如在线客服、社交聊天等用户可以即时收到对方发送的消息。
实时数据监控如股票行情、传感器数据监控等服务器可以实时将最新的数据推送给客户端。
多人在线游戏实现游戏中玩家之间的实时交互如位置更新、动作同步等。 二.代码示例
1.客户端代码
#include Clientdialog.h
#include QLabel
#include QWidget
#include QHBoxLayout
#include QVBoxLayout
#include QtCore
#include QDebug
#include iostream ClientDialog::ClientDialog(QWidget *parent) : QWidget(parent)
{ //layout1 QLabel *iplabel new QLabel(Server IP); m_iplineedit new QLineEdit; m_iplineedit-setText(127.0.0.1); QLabel *portlabel new QLabel(Server端口); m_portspinbox new QSpinBox; m_portspinbox-setRange(0,65535); m_portspinbox-setValue(5123); m_linkbutton new QPushButton(连接); m_disconnectbutton new QPushButton(断开); pButtonGroup new QButtonGroup(); pButtonGroup-setExclusive(true); m_linkbutton-setCheckable(true); m_disconnectbutton-setCheckable(true); pButtonGroup-addButton(m_linkbutton,0); pButtonGroup-addButton(m_disconnectbutton,1); QHBoxLayout *qhboxlayout1 new QHBoxLayout; qhboxlayout1-addWidget(iplabel); qhboxlayout1-addWidget(m_iplineedit); qhboxlayout1-addWidget(portlabel); qhboxlayout1-addWidget(m_portspinbox); qhboxlayout1-addWidget(m_linkbutton); qhboxlayout1-addWidget(m_disconnectbutton); //layout2 QLabel *sendmessagelabel new QLabel(发送消息); QHBoxLayout *qhboxlayout2 new QHBoxLayout; qhboxlayout2-addWidget(sendmessagelabel); //layout3 m_sendmessagetextedit new QTextEdit; m_sendmessagetextedit-setFixedHeight(50); m_sendbutton new QPushButton(发送); m_sendbutton-setFixedHeight(50); QHBoxLayout *qhboxlayout3 new QHBoxLayout; qhboxlayout3-addWidget(m_sendmessagetextedit); qhboxlayout3-addWidget(m_sendbutton); //layout4 QLabel *receivemessagelabel new QLabel(接收消息); QHBoxLayout *qhboxlayout4 new QHBoxLayout; qhboxlayout4-addWidget(receivemessagelabel); //layout5 m_receivemessageTextEdit new QTextEdit; QHBoxLayout *qhboxlayout5 new QHBoxLayout; qhboxlayout5-addWidget(m_receivemessageTextEdit); m_receivemessageTextEdit-setReadOnly(true); //layout6 statusLabel new QLabel(连接状态); m_clean new QPushButton(清除); QHBoxLayout *qhboxlayout6 new QHBoxLayout; qhboxlayout6-addWidget(statusLabel); qhboxlayout6-addStretch(); qhboxlayout6-addWidget(m_clean); // QVBoxLayout *mainlayout new QVBoxLayout; mainlayout-addLayout(qhboxlayout1,1); mainlayout-addLayout(qhboxlayout2,0.5); mainlayout-addLayout(qhboxlayout3,1); mainlayout-addLayout(qhboxlayout4,0.5); mainlayout-addLayout(qhboxlayout5,3); mainlayout-addLayout(qhboxlayout6,1); setLayout(mainlayout); setWindowTitle(Websocket Client); this-setFixedSize(800, 600); // 窗口固定为800x600像素无法缩放 connect(m_linkbutton,SIGNAL(clicked(bool)),this,SLOT(connectToServer())); connect(m_disconnectbutton,SIGNAL(clicked(bool)),this,SLOT(stopClicked())); connect(m_sendbutton,SIGNAL(clicked(bool)),this,SLOT(onSendButtonClicked())); connect(m_clean,SIGNAL(clicked(bool)),this,SLOT(onCleanButtonClicked())); connect(m_websocket,SIGNAL(connected()),this,SLOT(onconnected())); connect(m_websocket,SIGNAL(disconnected()),this,SLOT(closeConnection())); connect(m_websocket,SIGNAL(textMessageReceived(QString)),this,SLOT(onTextMessageReceived(QString)));
} ClientDialog::~ClientDialog()
{ m_websocket.errorString(); m_websocket.close();
} //断开连接操作
void ClientDialog::closeConnection(){ m_linkbutton-setEnabled(true); m_disconnectbutton-setEnabled(false); m_sendmessagetextedit-setEnabled(false); m_sendbutton-setEnabled(false); m_receivemessageTextEdit-setEnabled(false); m_clean-setEnabled(false); statusLabel-setText(tr(disconnected));
} //连接服务器
void ClientDialog::connectToServer()
{ QString path QString(ws://%1:%2).arg(m_iplineedit-text()).arg(m_portspinbox-text()); QUrl url QUrl(path); m_websocket.open(url);
} //连接上之后
void ClientDialog::onconnected(){ qDebug() hello word!; statusLabel-setText(tr(connected)); m_linkbutton-setEnabled(false); m_disconnectbutton-setEnabled(true); m_sendmessagetextedit-setEnabled(true); m_sendbutton-setEnabled(true); m_receivemessageTextEdit-setEnabled(true); m_clean-setEnabled(true);
} //收到消息
void ClientDialog::onTextMessageReceived(const QString message)
{ QString time current_date_time-currentDateTime().toString(yyyy.MM.dd hh:mm:ss.zzz ddd); m_receivemessageTextEdit-setText(time \r\n message: message);
} //断开
void ClientDialog::stopClicked()
{ m_websocket.close();
} //发送消息
void ClientDialog::onSendButtonClicked()
{ QString msg m_sendmessagetextedit-document()-toPlainText(); m_websocket.sendTextMessage(msg);
} //清除内容
void ClientDialog::onCleanButtonClicked()
{ m_receivemessageTextEdit-clear();
} 2.服务端代码
#include webserver.h
#include ui_webserver.h
#include QtCore/QVariant
#include QtWidgets/QApplication
#include QtWidgets/QButtonGroup
#include QtWidgets/QHeaderView
#include QtWidgets/QLabel
#include QtWidgets/QListWidget
#include QtWidgets/QPushButton
#include QtWidgets/QSpinBox
#include QtWidgets/QTextBrowser
#include QtWidgets/QWidget
#include QHBoxLayout
webserver::webserver(QWidget *parent) : QWidget(parent), ui(new Ui::webserver)
{ ui-setupUi(this); { //qhboxLayout1部分代码 QLabel* monitorLabel new QLabel(监听端口); m_monitorSpinBox new QSpinBox(); m_monitorSpinBox-setRange(0,65535); m_monitorSpinBox-setValue(5123); m_startButton new QPushButton(启动服务); m_stopButton new QPushButton(停止服务); m_stopButton-setEnabled(false); QHBoxLayout *qhboxLayout new QHBoxLayout; qhboxLayout-addWidget(monitorLabel); qhboxLayout-addWidget(m_monitorSpinBox); qhboxLayout-addWidget(m_startButton); qhboxLayout-addWidget(m_stopButton); //qhboxLayout2部分代码 QLabel* sendLabelnew QLabel(发送消息); sendLabel-setFixedHeight(30); QHBoxLayout *qhboxLayout2 new QHBoxLayout; qhboxLayout2-addWidget(sendLabel); //qhboxLayout3部分代码 m_sendTextedit new QTextEdit; m_sendTextedit new QTextEdit(); m_sendTextedit-setEnabled(false); m_sendTextedit-setFixedHeight(80); m_sendButton new QPushButton(发送); m_sendButton-setEnabled(false); m_sendButton-setFixedHeight(50); QHBoxLayout *qhboxlayout3 new QHBoxLayout; qhboxlayout3-addWidget(m_sendTextedit,2); qhboxlayout3-addWidget(m_sendButton,1); //qvboxlayout411 QLabel* receiveLabel new QLabel(接收消息); receiveLabel-setFixedHeight(30); m_receiveTextEdit new QTextEdit(); m_receiveTextEdit-setReadOnly(true); QVBoxLayout *qvboxlayout411 new QVBoxLayout; qvboxlayout411-addWidget(receiveLabel); qvboxlayout411-addWidget(m_receiveTextEdit); //qhboxlayout412 m_cleanButton new QPushButton(清除); m_cleanButton-setEnabled(false); QHBoxLayout *qhboxlayout412 new QHBoxLayout; qhboxlayout412-addStretch(); qhboxlayout412-addWidget(m_cleanButton); //qvboxlayout41 QVBoxLayout *qvboxlayout41 new QVBoxLayout; qvboxlayout41-addLayout(qvboxlayout411); qvboxlayout41-addLayout(qhboxlayout412); //qvboxlayout42 QLabel* linkclientLabelnew QLabel(连接客户端); linkclientLabel-setFixedHeight(30); m_linkclientListWidgetnew QListWidget; QVBoxLayout* qvboxlayout42 new QVBoxLayout; qvboxlayout42-addWidget(linkclientLabel); qvboxlayout42-addWidget(m_linkclientListWidget); //qvboxlayout4 QHBoxLayout *qhboxlayout4 new QHBoxLayout; qhboxlayout4-addLayout(qvboxlayout41,2); qhboxlayout4-addLayout(qvboxlayout42,1); //mainlayout QVBoxLayout *mainLayout new QVBoxLayout; mainLayout-addLayout(qhboxLayout,1); mainLayout-addLayout(qhboxLayout2,1); mainLayout-addLayout(qhboxlayout3,1); mainLayout-addLayout(qhboxlayout4,3); this-setLayout(mainLayout); this-setWindowTitle(Websocket Server -- Neo); this-setFixedSize(800, 600); // 窗口固定为800x600像素无法缩放 } m_WebSocketServernew QWebSocketServer(server,QWebSocketServer::NonSecureMode); connect(m_WebSocketServer,SIGNAL(newConnection()),this,SLOT(onNewConnection())); connect(m_WebSocketServer, SIGNAL(closed()), this, SLOT(onClosed())); connect(m_WebSocketServer, SIGNAL(serverError(QWebSocketProtocol::CloseCode)), this, SLOT(onServerError(QWebSocketProtocol::CloseCode))); connect(m_startButton,SIGNAL(clicked(bool)),this,SLOT(onStartButtonClick())); connect(m_stopButton,SIGNAL(clicked(bool)),this,SLOT(onStopButtonClick())); connect(m_cleanButton,SIGNAL(clicked(bool)),this,SLOT(onCleanButtonClick())); connect(m_sendButton,SIGNAL(clicked(bool)),this,SLOT(onSendButtonClick())); } webserver::~webserver()
{ if(m_WebSocketServer) { m_WebSocketServer-close(); } delete ui;
} //开启服务
void webserver::onStartButtonClick(){ int i_port m_monitorSpinBox-text().toInt(); m_WebSocketServer-listen(QHostAddress::Any,i_port); m_startButton-setEnabled(false); m_stopButton-setEnabled(true); qDebug()m_WebSocketServer-isListening(); qDebug()m_WebSocketServer-serverPort(); qDebug()m_WebSocketServer-serverAddress();
} //停止服务
void webserver::onStopButtonClick(){ m_startButton-setEnabled(true); m_stopButton-setEnabled(false); m_WebSocketServer-close();
} //发送信息
void webserver::onSendButtonClick(){ QString msg m_sendTextedit-document()-toPlainText(); int currenRow m_linkclientListWidget-currentRow();//当前单击选中ListWidget控件的行号 if(currenRow-1) { currenRow 0; } QString key m_linkclientListWidget-item(currenRow)-text(); if(_hashIpPort2PWebSocket.contains(key)) { _hashIpPort2PWebSocket.value(key)-sendTextMessage(msg); }
} void webserver::onCleanButtonClick(){ m_receiveTextEdit-clear();
} //连接上之后
void webserver::onNewConnection(){ qDebug() connect ok; m_startButton-setEnabled(false); m_stopButton-setEnabled(true); m_sendTextedit-setEnabled(true); m_sendButton-setEnabled(true); m_cleanButton-setEnabled(true); QWebSocket *pWebSocket m_WebSocketServer-nextPendingConnection(); connect(pWebSocket,SIGNAL(textMessageReceived(QString)),this,SLOT(slot_processTextMessage(QString))); connect(pWebSocket,SIGNAL(disconnected()),this,SLOT(slot_socketDisconnected())); connect(pWebSocket, SIGNAL(error(QAbstractSocket::SocketError)), this , SLOT(slot_error(QAbstractSocket::SocketError))); quint32 ipv4Address pWebSocket-peerAddress().toIPv4Address(); QString ipString QHostAddress(ipv4Address).toString(); _hashIpPort2PWebSocket.insert(QString(%1-%2).arg(ipString).arg(pWebSocket-peerPort()),pWebSocket); QString item QString(%1-%2).arg(ipString).arg(pWebSocket-peerPort()); m_linkclientListWidget-addItem(item);
} //停止之后
void webserver::onClosed()
{ QListQWebSocket * _listWebSocket _hashIpPort2PWebSocket.values(); for(int index 0; index _listWebSocket.size(); index) { _listWebSocket.at(index)-close(); } _hashIpPort2PWebSocket.clear(); m_linkclientListWidget-clear(); } //连接错误
void webserver::onServerError(QWebSocketProtocol::CloseCode closeCode)
{ QWebSocket *pWebSocket dynamic_castQWebSocket *(sender()); if(!pWebSocket) { return; }
} void webserver::slot_error(QAbstractSocket::SocketError error)
{ QWebSocket *pWebSocket dynamic_castQWebSocket *(sender()); if(!pWebSocket) { return; }
} //收到消息并显示
void webserver::slot_processTextMessage(QString message){ QWebSocket *pWebSocket dynamic_castQWebSocket *(sender()); if(!pWebSocket) { return; } QString time current_date_time-currentDateTime().toString(yyyy.MM.dd hh:mm:ss.zzz ddd); quint32 ipv4Address pWebSocket-peerAddress().toIPv4Address(); QString ipString QHostAddress(ipv4Address).toString(); QString item QString(IP: %1, port: %2).arg(ipString).arg(pWebSocket-peerPort()); m_receiveTextEdit-append(time \r\n item \r\n message: message \r\n); //qDebug() pWebSocket-peerAddress().toString(); //qDebug() Client IP address: ipString;
} //连接断开的操作
void webserver::slot_socketDisconnected(){ QWebSocket *pWebSocket dynamic_castQWebSocket *(sender()); if(!pWebSocket) { return; } //qDebug() __FILE__ __LINE__ __FUNCTION__; quint32 ipv4Address pWebSocket-peerAddress().toIPv4Address(); QString ipString QHostAddress(ipv4Address).toString(); QString item1 QString(%1-%2).arg(ipString).arg(pWebSocket-peerPort()); _hashIpPort2PWebSocket.remove(QString(%1-%2).arg(ipString).arg(pWebSocket-peerPort())); QListWidgetItem *item3; for(int i0;im_linkclientListWidget-count();i) { QString str m_linkclientListWidget-item(i)-text(); if(str item1) { item3 m_linkclientListWidget-takeItem(i); m_linkclientListWidget-removeItemWidget(item3); delete item3; } }
} void webserver::on_m_linkclientListWidget_clicked(const QModelIndex index)
{
int currenRow m_linkclientListWidget-currentRow();
} 3.完整工程代码下载
https://download.csdn.net/download/xieliru/90787178