概述
学习记录贴,参考了许多文档,
部分内容参考自 https://www.jianshu.com/p/a9497de4cbff
内容参考自 https://blog.csdn.net/cqchengdan/article/details/97619665#commentBox
内容参考自 https://blog.csdn.net/cqchengdan/article/details/97619483
有问题可以相互请教,这里就是对今天学习内容的总结。
1.模式分类
QWebSocketServer具有安全模式和非安全模式两种类型。体现在初始化类型值的不同
QWebSocketServer::SecureMode 为安全模式。需要配置SSL安全证书,QWebSocketServer::NOSecureMode为非安全模式,直接进行明文传输。
2.非安全模式下QWebsocket实现
2.1 服务器端
1.初始化QWebSocketServer
void DataAnalysisClient::init()
{
m_WebSocketServer = new QWebSocketServer("Server Name", QWebSocketServer::NoSecureMode, this);
}
2.实现服务器端接口
void DataAnalysisClient::onStartButtonClick()
{
int i_port = 6000;
m_WebSocketServer->listen(QHostAddress::Any, i_port);
m_sendEdit->append(QString("服务启动!"));
}
void DataAnalysisClient::onStopButtonClick()
{
m_WebSocketServer->close();
for (int i=0;i<m_clients.size();i++)
{
m_clients.at(i)->close();
}
m_sendEdit->append(QString("服务停止!"));
}
void DataAnalysisClient::onSendButtonClick()
{
QString msg = "服务端发送数据!";
for (int i=0;i<m_clients.size();i++)
{
m_clients.at(i)->sendTextMessage(msg);
}
}
void ACMSLIB::DataAnalysisClient::onNewConnection()
{
// 读取到下一个等待连接的套接字,套接字需要显式删除
pSocket = m_WebSocketServer->nextPendingConnection();
connect(pSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(processTextMessage(QString)));
connect(pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
QString item = pSocket->peerAddress().toString();
QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz");
QString ip = m_WebSocketServer->serverAddress().toString();
int port = m_WebSocketServer->serverPort();
QString url = m_WebSocketServer->serverUrl().toString();
m_sendEdit->append(QString("%1 + "" 新建连接:IP为%2").arg(time).arg(item));
m_sendEdit->append(QString("IP:%1 + 端口号:%2 + url:%3").arg(ip).arg(port).arg(url));
m_clients << pSocket;
}
//收到消息并显示
void DataAnalysisClient::processTextMessage(QString message)
{
QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz");
QString item = pSocket->peerAddress().toString();
m_recEdit->append(time + "" + item + "n" + message);
}
void DataAnalysisClient::socketDisconnected()
{
QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz");
QString item = pSocket->peerAddress().toString();
m_recEdit->append(QString(time + "" + item + "n" + "失去连接:IP为%1").arg(item));
m_recEdit->append("n");
}
2.2 客户端
1.初始化
// 操作按钮
connect(m_startBtn, SIGNAL(clicked(bool)), this, SLOT(connectToServer()));
connect(m_closeBtn, SIGNAL(clicked(bool)), this, SLOT(stopClicked()));
connect(m_sendBtn, SIGNAL(clicked(bool)), this, SLOT(onSendButtonClicked()));
// 数据传输
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)));
2.接口实现
void Widget::connectToServer()
{
QString IP= "***.***.***.***";
QString prot = "6000";
QString path = QString("wss://%1:%2").arg(IP).arg(prot);
QUrl url = QUrl(path);
m_websocket.open(url);
// 错误提示
connect(&m_websocket, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(readError(QAbstractSocket::SocketError)));
}
void Widget::onTextMessageReceived(const QString &message)
{
m_recEdit->append("-----------------------------1");
QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
m_recEdit->append(time + "n" + message);
}
void Widget::closeConnection()
{
}
void Widget::stopClicked()
{
m_websocket.close();
}
void Widget::onconnected()
{
m_recEdit->append("连接成功");
}
void Widget::onSendButtonClicked()
{
QString msg = "客户端发送数据";
m_websocket.sendTextMessage(msg);
}
void Widget::onCleanButtonClicked()
{
}
void Widget::readError(QAbstractSocket::SocketError err)
{
qDebug () << "连接Error!";
}
3.安全模式下QWebsocket实现
3.1 证书准备
QWebsocket安全模式需要对SSL进行验证,QT本身不支持SSL验证,手动下载openSSL
3.2 生成证书
下载安装好后,打开openssl.exe
3.2.1 生成密钥
genrsa -des3 -out server.key 2048
说明:生成rsa私钥,des3算法,2048位强度,server.key是秘钥文件名。
注意:生成私钥,需要提供一个至少4位的密码。
3.2.2 生成CSR(证书签名请求)
req -new -key server.key -out server.csr
说明:需要依次输入国家,地区,城市,组织,组织单位,Common Name和Email。其中Common Name,可以写自己的名字或者域名,如果要支持https,Common Name应该与域名保持一致,否则会引起浏览器警告。
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Beijing
Locality Name (eg, city) []:Beijing
Organization Name (eg, company) [Internet Widgits Pty Ltd]:IT
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:IT
Email Address []:123456789@qq.com
3.2.3 删除私钥中的密码
rsa -in server.key -out server_no.key
备注:必须操作,不删除的话,在不鉴定客户端证书的情况下也无法连接成功,
在3.2.1创建私钥的过程中,由于必须要指定一个密码。而这个密码会带来一个副作用,那就是在每次Apache启动Web服务器时,都会要求输入密码,这显然非常不方便。要删除私钥中的密码,操作如下:
3.2.4 生成自签名证书
x509 -req -days 365 -in server.csr -signkey server_no.key -out server.crt
由此得到了签名证书server.crt和私钥server_no.key
3.3 设计服务端
在原有使用非安全模式的WebsockeServer服务的基础上添加一些签名证书和验证
1.初始化QWebSocketServer
void DataAnalysisClient::init()
{
m_WebSocketServer = new QWebSocketServer("Server Name", QWebSocketServer::SecureMode, this);
//
QFile certFile(":server.crt");
QFile keyFile(":server.key");
if(!certFile.open(QIODevice::ReadOnly)){
qDebug() << "certfile open failed...";
}
if(!keyFile.open(QIODevice::ReadOnly)){
qDebug() << "keyfile open failed...";
}
QSslCertificate cert(&certFile, QSsl::Pem);
QSslKey key(&keyFile, QSsl::Rsa, QSsl::Pem);
certFile.close();
keyFile.close();
QSslConfiguration conf = m_WebSocketServer->sslConfiguration();
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
conf.setLocalCertificate(cert);
conf.setPrivateKey(key);
conf.setProtocol(QSsl::TlsV1SslV3);
m_WebSocketServer->setSslConfiguration(conf);
}
3.4 设计客户端
void Widget::connectToServer()
{
QString IP= "***.***.***.***";
QString prot = "6000";
QString path = QString("wss://%1:%2").arg(IP).arg(prot);
QUrl url = QUrl(path);
QSslConfiguration conf = m_websocket.sslConfiguration();
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
conf.setProtocol(QSsl::TlsV1SslV3);
m_websocket.setSslConfiguration(conf);
}
conf.setPeerVerifyMode(QSslSocket::VerifyNone);使用跳过证书验证的方式使用了SSL的安全传输,实现了数据加密功能。
3.5 使用证书验证
修改验证方式为QSslSocket::VerifyPeer,客户端初始化设置为
{
QString IP= "***.***.***.***";
QString prot = "6000";
QString path = QString("wss://%1:%2").arg(IP).arg(prot);
QUrl url = QUrl(path);
QSslConfiguration conf = m_websocket.sslConfiguration();
//conf.setPeerVerifyMode(QSslSocket::VerifyNone);
conf.setPeerVerifyMode(QSslSocket::VerifyPeer);
conf.setProtocol(QSsl::TlsV1SslV3);
m_websocket.setSslConfiguration(conf);
//解决自签名证书不受信赖问题,VerifyNone不需添加以下代码
QList<QSslCertificate> certlist = QSslCertificate::fromPath("F:/myself/server.crt");
QSslError error(QSslError::SelfSignedCertificate, certlist.at(0));
QList<QSslError> expectedErrors;
expectedErrors.append(error);
m_websocket.ignoreSslErrors(expectedErrors);
}
此方法暂时不适用,websocket的报error提示SocketError::SslHandshakeFailedError错误,暂时不知道原因。
最后
以上就是碧蓝电灯胆为你收集整理的使用QWebSocketServer实现网络数据传输的全部内容,希望文章能够帮你解决使用QWebSocketServer实现网络数据传输所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复