websockets wws server c++ code
时间: 2023-07-15 12:14:31 浏览: 97
websocket c++
4星 · 用户满意度95%
以下是一个基本的WebSocket服务器的C++代码示例:
```
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <atomic>
#include <stdexcept>
#include <sstream>
#include <map>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#define MAX_BUFFER_LENGTH 1024
#define BACKLOG 10
// 自定义异常类
class SocketException : public std::runtime_error {
public:
SocketException(const std::string& message) : std::runtime_error(message) {}
};
// WebSocket消息类
class WebSocketMessage {
public:
WebSocketMessage() : m_opcode(0), m_payload() {}
WebSocketMessage(const std::string& payload, uint8_t opcode) : m_opcode(opcode), m_payload(payload) {}
std::string getPayload() const {
return m_payload;
}
uint8_t getOpcode() const {
return m_opcode;
}
private:
uint8_t m_opcode; // 操作码
std::string m_payload; // 消息负载
};
// WebSocket连接类
class WebSocketConnection {
public:
WebSocketConnection(int socketFd, sockaddr_in clientAddr) : m_socketFd(socketFd), m_clientAddr(clientAddr) {}
~WebSocketConnection() {
close(m_socketFd);
}
void send(const WebSocketMessage& message) {
std::string payload = message.getPayload();
uint8_t opcode = message.getOpcode();
uint8_t header[14];
size_t headerLength = 2;
header[0] = 0x80 | (opcode & 0x0f); // FIN(1) + opcode(4)
if (payload.length() <= 125) {
header[1] = payload.length(); // MASK(0) + payload length(7)
} else if (payload.length() <= 0xffff) {
header[1] = 126; // MASK(0) + payload length(7)
uint16_t len = htons(payload.length());
memcpy(header + 2, &len, sizeof(len));
headerLength += 2;
} else {
header[1] = 127; // MASK(0) + payload length(7)
uint64_t len = htonll(payload.length());
memcpy(header + 2, &len, sizeof(len));
headerLength += 8;
}
std::vector<uint8_t> mask(4);
for (int i = 0; i < 4; ++i) {
mask[i] = rand() % 256;
}
std::vector<uint8_t> maskedPayload(payload.length());
for (size_t i = 0; i < payload.length(); ++i) {
maskedPayload[i] = payload[i] ^ mask[i % 4];
}
std::vector<uint8_t> headerAndMaskedPayload(headerLength + mask.size() + maskedPayload.size());
memcpy(headerAndMaskedPayload.data(), header, headerLength);
memcpy(headerAndMaskedPayload.data() + headerLength, mask.data(), mask.size());
memcpy(headerAndMaskedPayload.data() + headerLength + mask.size(), maskedPayload.data(), maskedPayload.size());
int n = write(m_socketFd, headerAndMaskedPayload.data(), headerAndMaskedPayload.size());
if (n < 0) {
throw SocketException("Error sending message");
}
}
WebSocketMessage receive() {
uint8_t buffer[MAX_BUFFER_LENGTH];
int n = read(m_socketFd, buffer, MAX_BUFFER_LENGTH);
if (n < 0) {
throw SocketException("Error receiving message");
}
if (n == 0) {
// 连接已经关闭
return WebSocketMessage();
}
uint8_t b1 = buffer[0];
uint8_t b2 = buffer[1];
uint8_t opcode = b1 & 0x0f;
bool fin = (b1 & 0x80) != 0;
bool masked = (b2 & 0x80) != 0;
uint64_t payloadLength = b2 & 0x7f;
size_t headerLength;
if (payloadLength <= 125) {
headerLength = 2;
} else if (payloadLength == 126) {
headerLength = 4;
uint16_t len;
memcpy(&len, buffer + 2, sizeof(len));
payloadLength = ntohs(len);
} else {
headerLength = 10;
uint64_t len;
memcpy(&len, buffer + 2, sizeof(len));
payloadLength = ntohll(len);
}
std::vector<uint8_t> mask(4);
if (masked) {
memcpy(mask.data(), buffer + headerLength, mask.size());
}
std::vector<uint8_t> payload(payloadLength);
memcpy(payload.data(), buffer + headerLength + mask.size(), payloadLength);
if (masked) {
for (size_t i = 0; i < payloadLength; ++i) {
payload[i] ^= mask[i % 4];
}
}
return WebSocketMessage(std::string(payload.begin(), payload.end()), opcode);
}
std::string getClientAddress() const {
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(m_clientAddr.sin_addr), addr, INET_ADDRSTRLEN);
return std::string(addr) + ":" + std::to_string(ntohs(m_clientAddr.sin_port));
}
private:
int m_socketFd;
sockaddr_in m_clientAddr;
};
// WebSocket服务器类
class WebSocketServer {
public:
WebSocketServer(const std::string& address, int port) : m_address(address), m_port(port), m_stop(false), m_socketFd(-1), m_connections() {}
~WebSocketServer() {
stop();
}
void start() {
// 创建socket
m_socketFd = socket(AF_INET, SOCK_STREAM, 0);
if (m_socketFd < 0) {
throw SocketException("Error creating socket");
}
// 设置socket为非阻塞
fcntl(m_socketFd, F_SETFL, O_NONBLOCK);
// 绑定地址和端口
sockaddr_in serverAddr;
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr(m_address.c_str());
serverAddr.sin_port = htons(m_port);
if (bind(m_socketFd, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
throw SocketException("Error binding socket");
}
// 监听端口
if (listen(m_socketFd, BACKLOG) < 0) {
throw SocketException("Error listening on socket");
}
std::cout << "WebSocket server started at " << m_address << ":" << m_port << std::endl;
// 接受连接
while (!m_stop) {
sockaddr_in clientAddr;
socklen_t clientAddrLen = sizeof(clientAddr);
int clientSocketFd = accept(m_socketFd, (sockaddr*)&clientAddr, &clientAddrLen);
if (clientSocketFd >= 0) {
// 新连接
std::cout << "New connection from " << getClientAddress(clientAddr) << std::endl;
m_connections.push_back(std::make_shared<WebSocketConnection>(clientSocketFd, clientAddr));
}
// 等待一段时间再接受连接
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void stop() {
m_stop = true;
close(m_socketFd);
std::cout << "WebSocket server stopped" << std::endl;
}
std::vector<std::shared_ptr<WebSocketConnection>> getConnections() const {
return m_connections;
}
private:
std::string m_address;
int m_port;
std::atomic<bool> m_stop;
int m_socketFd;
std::vector<std::shared_ptr<WebSocketConnection>> m_connections;
std::string getClientAddress(sockaddr_in clientAddr) const {
char addr[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(clientAddr.sin_addr), addr, INET_ADDRSTRLEN);
return std::string(addr) + ":" + std::to_string(ntohs(clientAddr.sin_port));
}
};
int main(int argc, char* argv[]) {
// 创建WebSocket服务器
WebSocketServer server("127.0.0.1", 8080);
// 启动服务器
try {
server.start();
} catch (const SocketException& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
```
这是一个基本的WebSocket服务器实现,可以接受连接并收发消息。但这只是一个最简单的例子,实际上WebSocket协议还有很多复杂的细节需要处理,比如掩码、分片等等。如果要使用WebSocket,建议使用现成的库来实现,例如 Boost.Beast。
阅读全文