WebSocket에 대한 자세한 설명 및 QWebSocket을 사용하여 서버 및 클라이언트 구현(코드 예제 포함)

목차

1. WebSocket 탄생 배경

2. 웹소켓의 특징:

3. 웹소켓 소개

4. 웹소켓의 장점

5. QWebSocket 통신 클라이언트:

6. QWebSocket 통신—서버:


1. WebSocket 탄생 배경

초기에는 많은 웹사이트에서 푸시 기술을 구현하기 위해 폴링(단기 폴링이라고도 함)을 사용했습니다.

폴링은 브라우저가 정기적으로 서버에 HTTP 요청을 보낸 다음 서버가 최신 데이터를 클라이언트에 반환하는 것을 의미합니다.

2. 웹소켓의 특징:

1) TCP 프로토콜을 기반으로 구축되어 서버 측 구현이 비교적 쉽습니다.

2) HTTP 프로토콜과의 호환성이 좋습니다. 기본 포트도 80과 443입니다.

그리고 핸드셰이크 단계에서는 HTTP 프로토콜을 사용하므로 핸드셰이크 중에 차단하기가 쉽지 않고 다양한 HTTP 프록시 서버를 통과할 수 있습니다.

3) 데이터 형식은 상대적으로 가볍고 성능 오버헤드가 낮으며 통신이 효율적입니다.

4) 텍스트 또는 바이너리 데이터를 보낼 수 있습니다.

5) 출처 제한이 없으며 클라이언트는 모든 서버와 통신할 수 있습니다.

6) 프로토콜 식별자는 ws(또는 암호화된 경우 wss)이고 서버 주소는 URL입니다.

ws://example.com:80/some/path와 같습니다.

3. 웹소켓 소개

WebSocket은 단일 TCP 연결을 통한 전이중 통신을 가능하게 하는 네트워크 전송 프로토콜이며 OSI 모델의 애플리케이션 계층에 있습니다.

4. 웹소켓의 장점

1) 제어 오버헤드 감소: 연결이 생성된 후 서버와 클라이언트 간에 데이터가 교환될 때 프로토콜 제어에 사용되는 패킷 헤더가 상대적으로 작습니다.

2) 더욱 강력한 실시간 성능: 프로토콜이 전이중이므로 서버는 언제든지 클라이언트에 적극적으로 데이터를 보낼 수 있습니다. 서버가 응답하기 전에 클라이언트가 요청을 시작할 때까지 기다려야 하는 HTTP 요청과 비교하면 지연 시간이 훨씬 적습니다.

3) 연결 상태 유지: HTTP와 달리 WebSocket은 먼저 연결을 생성해야 하므로 상태 저장 프로토콜이 되며 일부 상태 정보는 후속 통신 중에 생략될 수 있습니다.

4) 더 나은 바이너리 지원: WebSocket은 HTTP보다 바이너리 콘텐츠를 더 쉽게 처리할 수 있는 바이너리 프레임을 정의합니다.

5) 확장 지원 가능: WebSocket은 확장을 정의하고 사용자는 프로토콜을 확장하고 일부 맞춤형 하위 프로토콜을 구현할 수 있습니다.

WebSocket은 위와 같은 장점을 가지고 있기 때문에 인스턴트 메시징/IM, 실시간 오디오 및 비디오, 온라인 교육, 게임 등의 분야에서 널리 사용됩니다.

5. QWebSocket 통신 클라이언트:

사용된 일부 주요 인터페이스: (주요 단계)

#include <QWebSocket>
QWebSocket* m_pDataRecvWS = new QWebSocket();
m_pDataRecvWS->open(QUrl("URL"));//形如:ws://example.com:80/some/path

//客户端发出请求后,服务器会处理发相应的信号:
//1、连接成功后
connected();

//2、连接失败
disconnected();

//3、收到数据
textMessageReceived();

//常用的函数--------------------------------------
//发送消息
sendTextMessage()

간단한 예:

//例子
QTimer m_timer = new QTimer();//重连计时器
if (m_pDataRecvWS == nullptr)
{
   m_pDataRecvWS = new QWebSocket();
   connect(m_pDataRecvWS, &QWebSocket::disconnected, this, &WebSocketClient::slotOnDisConnected, Qt::AutoConnection);
   connect(m_pDataRecvWS, &QWebSocket::textMessageReceived, this, &WebSocketClient::slotOnTextReceived, Qt::AutoConnection);
   connect(m_pDataRecvWS, &QWebSocket::connected, this, &WebSocketClient::slotOnConnected, Qt::AutoConnection);
   connect(m_timer, QTimer::timeout, this, &WebSocketClient::slotReconnect, Qt::AutoConnection);
   m_pDataRecvWS->open(QUrl(m_strURL));
}

//连接成功-关闭重连的计时器
void WebSocketClient::slotOnConnected()
{
    m_bConnectStatus = true;
    m_timer->stop();
}

//连接失败-启动计时器准备重连
void WebSocketClient::slotOnDisConnected()
{
    m_bConnectStatus = false;
    m_timer->start(3000);/*-<当连接失败时,触发重连计时器,设置计数周期为3秒 */
}

//重连
void WebSocketClient::slotReconnect()
{
    m_pDataRecvWS->abort();
    m_pDataRecvWS->open(QUrl(m_strURL));
}

//收到消息
void WebSocketClient::slotOnTextReceived(const QString& msg)
{
   // todo
}


6. QWebSocket 통신—서버:

사용된 일부 주요 인터페이스: (주요 단계)

//声明变量
QWebSocketServer *m_pWebSocketServer;
QList<QWebSocket *> m_clients;//保存连接的客户端
unsigned short mPort;//端口号
QString mServerName;//服务器名字

//1、创建服务器
m_pWebSocketServer = new QWebSocketServer(mServerName, QWebSocketServer::NonSecureMode, this);

//2、监听
m_pWebSocketServer->listen(QHostAddress::LocalHost, mPort);//端口号

//3、有新的连接,会发这个信号
connect(m_pWebSocketServer, &QWebSocketServer::newConnection, this, &WebSocketServer::onNewConnection);


//4、获得新的客户端nextPendingConnection
void WebSocketServer::onNewConnection()
{
    auto pSocket = m_pWebSocketServer->nextPendingConnection();
    pSocket->setParent(this);
    connect(pSocket, &QWebSocket::textMessageReceived, this, &WebSocketServer::processMessage);
    connect(pSocket, &QWebSocket::disconnected, this, &WebSocketServer::socketDisconnected);
    m_clients << pSocket;//放进去客户端列表
}

//5、接收到信息
void WebSocketServer::processMessage(const QString &message)
{
    QWebSocket *pSender = qobject_cast<QWebSocket *>(sender());
    for (QWebSocket *pClient : qAsConst(m_clients))
    {
        emit processServerMessage(message);
        if (pClient != pSender) //don't echo message back to sender
            pClient->sendTextMessage(message);
    }
}

//6、断开连接
void WebSocketServer::socketDisconnected()
{
    QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
    QTextStream(stdout) << getIdentifier(pClient) << " disconnected!\n";
    if (pClient)
    {
        m_clients.removeAll(pClient);
        pClient->deleteLater();
    }
}

추천

출처blog.csdn.net/bigger_belief/article/details/130725799