本篇博文主要是提供了一个基于tcp封装的websocket服务端,没有使用任何的网络库,这样便于自我学习,关于这个协议的一些概念的话,大家可以执行百度了解。 客户端的话,大家可以找一些在线网站模拟websocket客户端即可。代码的话,由select+tcp改装而成,主要适用于windows平台,大家如果有兴趣也可以使用epoll来实现。下面给出具体的代码,具体可以用vs进行单步调试观察一下包的格式,这样对于理解这个协议的理解是非常有帮助的。
//base64.cpp
#include "base64.h"
#include <iostream>
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while ((i++ < 3))
ret += '=';
}
return ret;
}
std::string base64_decode(std::string const& encoded_string) {
size_t in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j < 4; j++)
char_array_4[j] = 0;
for (j = 0; j < 4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
base64.h
#pragma once
#include <string>
std::string base64_encode(unsigned char const*, unsigned int len);
std::string base64_decode(std::string const& s);
//sha1.cpp
#include "sha1.h"
SHA1::SHA1()
{
Reset();
}
SHA1::~SHA1()
{
}
void SHA1::Reset()
{
Length_Low = 0;
Length_High = 0;
Message_Block_Index = 0;
H[0] = 0x67452301;
H[1] = 0xEFCDAB89;
H[2] = 0x98BADCFE;
H[3] = 0x10325476;
H[4] = 0xC3D2E1F0;
Computed = false;
Corrupted = false;
}
bool SHA1::Result(unsigned *message_digest_array)
{
int i;
if (Corrupted)
{
return false;
}
if (!Computed)
{
PadMessage();
Computed = true;
}
for(i = 0; i < 5; i++)
{
message_digest_array[i] = H[i];
}
return true;
}
void SHA1::Input( const unsigned char *message_array,
unsigned length)
{
if (!length)
{
return;
}
if (Computed || Corrupted)
{
Corrupted = true;
return;
}
while(length-- && !Corrupted)
{
Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
Length_Low += 8;
Length_Low &= 0xFFFFFFFF;
if (Length_Low == 0)
{
Length_High++;
Length_High &= 0xFFFFFFFF;
if (Length_High == 0)
{
Corrupted = true;
}
}
if (Message_Block_Index == 64)
{
ProcessMessageBlock();
}
message_array++;
}
}
void SHA1::Input( const char *message_array,
unsigned length)
{
Input((unsigned char *) message_array, length);
}
void SHA1::Input(unsigned char message_element)
{
Input(&message_element, 1);
}
void SHA1::Input(char message_element)
{
Input((unsigned char *) &message_element, 1);
}
SHA1& SHA1::operator<<(const char *message_array)
{
const char *p = message_array;
while(*p)
{
Input(*p);
p++;
}
return *this;
}
SHA1& SHA1::operator<<(const unsigned char *message_array)
{
const unsigned char *p = message_array;
while(*p)
{
Input(*p);
p++;
}
return *this;
}
SHA1& SHA1::operator<<(const char message_element)
{
Input((unsigned char *) &message_element, 1);
return *this;
}
SHA1& SHA1::operator<<(const unsigned char message_element)
{
Input(&message_element, 1);
return *this;
}
void SHA1::ProcessMessageBlock()
{
const unsigned K[] = {
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t;
unsigned temp;
unsigned W[80];
unsigned A, B, C, D, E;
for(t = 0; t < 16; t++)
{
W[t] = ((unsigned) Message_Block[t * 4]) << 24;
W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
}
for(t = 16; t < 80; t++)
{
W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = H[0];
B = H[1];
C = H[2];
D = H[3];
E = H[4];
for(t = 0; t < 20; t++)
{
temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 20; t < 40; t++)
{
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 40; t < 60; t++)
{
temp = CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 60; t < 80; t++)
{
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
H[0] = (H[0] + A) & 0xFFFFFFFF;
H[1] = (H[1] + B) & 0xFFFFFFFF;
H[2] = (H[2] + C) & 0xFFFFFFFF;
H[3] = (H[3] + D) & 0xFFFFFFFF;
H[4] = (H[4] + E) & 0xFFFFFFFF;
Message_Block_Index = 0;
}
void SHA1::PadMessage()
{
if (Message_Block_Index > 55)
{
Message_Block[Message_Block_Index++] = 0x80;
while(Message_Block_Index < 64)
{
Message_Block[Message_Block_Index++] = 0;
}
ProcessMessageBlock();
while(Message_Block_Index < 56)
{
Message_Block[Message_Block_Index++] = 0;
}
}
else
{
Message_Block[Message_Block_Index++] = 0x80;
while(Message_Block_Index < 56)
{
Message_Block[Message_Block_Index++] = 0;
}
}
Message_Block[56] = (Length_High >> 24) & 0xFF;
Message_Block[57] = (Length_High >> 16) & 0xFF;
Message_Block[58] = (Length_High >> 8) & 0xFF;
Message_Block[59] = (Length_High) & 0xFF;
Message_Block[60] = (Length_Low >> 24) & 0xFF;
Message_Block[61] = (Length_Low >> 16) & 0xFF;
Message_Block[62] = (Length_Low >> 8) & 0xFF;
Message_Block[63] = (Length_Low) & 0xFF;
ProcessMessageBlock();
}
unsigned SHA1::CircularShift(int bits, unsigned word)
{
return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
}
//sha1.h
#ifndef _SHA1_H_
#define _SHA1_H_
class SHA1
{
public:
SHA1();
virtual ~SHA1();
void Reset();
bool Result(unsigned *message_digest_array);
void Input( const unsigned char *message_array,
unsigned length);
void Input( const char *message_array,
unsigned length);
void Input(unsigned char message_element);
void Input(char message_element);
SHA1& operator<<(const char *message_array);
SHA1& operator<<(const unsigned char *message_array);
SHA1& operator<<(const char message_element);
SHA1& operator<<(const unsigned char message_element);
private:
void ProcessMessageBlock();
void PadMessage();
inline unsigned CircularShift(int bits, unsigned word);
unsigned H[5];
unsigned Length_Low;
unsigned Length_High;
unsigned char Message_Block[64];
int Message_Block_Index;
bool Computed;
bool Corrupted;
};
#endif
上面几个文件提供的接口可以用来进行数据的加密, 这个如果大家有需要可以考虑一下,具体的用法,可以看如下的文件。(当然,如果服务端使用了,客户端那么也是需要使用的)
#include "debug_log.h"
void DEBUG_LOG(const char* msg, ...) {
char message[256] = { 0 };
va_list args;
va_start(args, msg);
vsprintf(message, msg, args);
va_end(args);
Debug_LOG::log()->write_log(message);
}
Debug_LOG* Debug_LOG::m_log = NULL;
Debug_LOG::Debug_LOG() :
tim(0),
t(NULL),
fp(NULL),
filepath(),
message(),
last_log_time()
{
#ifdef __WRITE_FILE__
create_log_file();
#endif
}
Debug_LOG::~Debug_LOG() {
#ifdef __WRITE_FILE__
fclose(fp);
#endif
}
void Debug_LOG::create_log_file() {
if (fp != NULL)
fclose(fp);
sprintf(filepath, "./log/debuglog_");
time(&tim);
t = localtime(&tim);
memcpy(&last_log_time, t, sizeof(struct tm));
sprintf(filepath + 15, "%02d_%02d", t->tm_mon + 1, t->tm_mday);
fp = fopen(filepath, "a+");
}
Debug_LOG* Debug_LOG::log() {
if (m_log == NULL) {
m_log = new Debug_LOG();
}
return m_log;
}
void Debug_LOG::write_log(const char* msg) {
time(&tim);
t = localtime(&tim);
sprintf(message, "[%02d:%02d:%02d] %s\n", t->tm_hour, t->tm_min, t->tm_sec, msg);
#ifdef __WRITE_FILE__
if (t->tm_mday != last_log_time.tm_mday || t->tm_mon != last_log_time.tm_mon
|| t->tm_year != last_log_time.tm_year)
create_log_file();
fwrite(message, strlen(message), 1, fp);
fflush(fp);
#else
printf("\n%s", message);
fflush(stdout);
#endif
}
#pragma once
#ifndef __debug_log__
#define __debug_log__
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
void DEBUG_LOG(const char* msg, ...);
class Debug_LOG
{
private:
Debug_LOG();
~Debug_LOG();
void create_log_file();
public:
static Debug_LOG* log();
void write_log(const char* msg);
private:
static Debug_LOG* m_log;
time_t tim;
struct tm* t;
FILE* fp;
char filepath[32];
char message[256];
struct tm last_log_time;
};
#endif
这两个是用来调试的。
//以下的代码是核心部分。
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include "debug_log.h"
#include "network_interface.h"
#include "websocket_respond.h"
#include "websocket_request.h"
#include <winsock2.h>
#include "windows.h"
#include "time.h"
WEB_SOCKET_ISH5_MAP websocket_ish5run_map_;
WEB_SOCKET_ISH5_MAP websocket_ish5configdata_map_;
WEB_SOCKET_ISH5_MAP websocket_ish5gamedata_map_;
Network_Interface* Network_Interface::m_network_interface = NULL;
Network_Interface::Network_Interface() : listenfd_(0), websocket_handler_map_()
{
if(init() != 0)
{
exit(1);
}
}
Network_Interface::~Network_Interface()
{
WSACleanup();
}
void Network_Interface::run()
{
select_loop();
}
Network_Interface* Network_Interface::get_share_network_interface()
{
if(m_network_interface == NULL)
m_network_interface = new Network_Interface();
return m_network_interface;
}
int Network_Interface::init()
{
WSADATA wsaData;
int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(err != 0)
{
std::cout << "Load WinSock Failed!\n";
return -1;
}
listenfd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(listenfd_ == -1)
{
DEBUG_LOG("create socket error!\n");
return -1;
}
int option = 1;
if(setsockopt(listenfd_, SOL_SOCKET, SO_REUSEADDR, (char*)&option, sizeof(int)) < 0)
{
return -1;
}
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
if(bind(listenfd_, (struct sockaddr*)(&server_addr), sizeof(server_addr)) == -1)
{
DEBUG_LOG("bind socket error!\n");
return -1;
}
if(listen(listenfd_, 15) == -1)
{
DEBUG_LOG("listen socket error!\n");
return -1;
}
FD_ZERO(&reads);
FD_SET(listenfd_, &reads);
fd_max = listenfd_;
return 0;
}
void Network_Interface::select_event(int fd, bool flag)
{
if(flag)
{
if(fd_max < fd)
{
fd_max = fd;
}
FD_SET(fd, &reads);
websocket_handler_map_[fd] = new Websocket_Handler(fd);
websocket_ish5run_map_[fd] = true;
if(fd != listenfd_)
{
DEBUG_LOG("fd: %d add select loop", fd);
}
}
else
{
FD_CLR(fd, &reads);
closesocket(fd);
delete websocket_handler_map_[fd];
websocket_handler_map_.erase(fd);
websocket_ish5run_map_.erase(fd);
websocket_ish5configdata_map_.erase(fd);
websocket_ish5gamedata_map_.erase(fd);
DEBUG_LOG("fd: %d del select loop", fd);
}
}
int Network_Interface::select_loop()
{
struct sockaddr_in clnt_adr;
int fd_num, i, fd = 0, bufflen = 0;
int clilen = sizeof(SOCKADDR);
while(true)
{
cpy_reads = reads;
if((fd_num = select(fd_max + 1, &cpy_reads, 0, 0, NULL)) == -1)
break;
if(fd_num == 0)
continue;
for(i = 0; i < fd_max + 1; i++)
{
if(FD_ISSET(i, &cpy_reads))
{
if(i == listenfd_)
{
fd = accept(listenfd_, (struct sockaddr*)&clnt_adr, &clilen);
select_event(fd, true);
}
else
{
Websocket_Handler* handler = websocket_handler_map_[i];
if(handler == NULL)
{
continue;
}
if((bufflen = recv(i, handler->getbuff(), BUFFLEN, 0)) == 0)
{
select_event(i, false);
}
else if(bufflen == 8)
{
continue;
}
else if(bufflen < 0)
{
break;
}
else
{
handler->process();
}
}
}
}
}
return 0;
}
//
#ifndef __WEBSOCKET_HANDLER__
#define __WEBSOCKET_HANDLER__
#include <winsock2.h>
#include <iostream>
#include <map>
#include <sstream>
#include "base64.h"
#include "sha1.h"
#include "debug_log.h"
#include "websocket_request.h"
#define MAGIC_KEY "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
enum WEBSOCKET_STATUS
{
WEBSOCKET_UNCONNECT = 0,
WEBSOCKET_HANDSHARKED = 1,
};
typedef std::map<std::string, std::string> HEADER_MAP;
class Websocket_Handler
{
public:
Websocket_Handler(int fd);
~Websocket_Handler();
int process();
inline char* getbuff();
private:
int handshark();
void parse_str(char* request);
int fetch_http_info();
int send_data(char* buff);
private:
Websocket_Request* request_;
char buff_[2048];
WEBSOCKET_STATUS status_;
HEADER_MAP header_map_;
int fd_;
};
inline char* Websocket_Handler::getbuff()
{
return buff_;
}
#endif
//
#include <winsock2.h>
#include "websocket_request.h"
#include "network_interface.h"
#include <json/json.h>
Websocket_Request::Websocket_Request(int fd) : fd_(fd),fin_(), opcode_(), mask_(),
masking_key_(),
payload_length_(),
payload_()
{
_M_h5aes.setkey("DlClientPost2019");
}
void Websocket_Request::runconfigdata(char *str, int len, int socket)
{
char* runconfigdata = new char[len + 1];
memcpy(runconfigdata, str, len + 1);
printf("\n\nrunconfigdata = %s\n", str);
}
void Websocket_Request::rungamedata(char* str, int len, int socket)
{
}
int Websocket_Request::websockettoh5(char *content, int length, int fd)
{
if(length == 30)
{
return 0;
}
printf("content = %s,length = %d\n", content,length);
char* data = new char[length + 1];
memcpy(data, content, length + 1);
printf("data = %s,length = %d\n", data, length);
BYTE* de_base64;
BYTE* de_payload;
int ret = _M_h5aes.base64_decode((char*)data, &de_base64);
if(ret > 0)
{
ret = _M_h5aes.decrypt(de_base64, ret, &de_payload);
if(ret > 0)
{
de_payload[ret] = 0;
}
else
{
return 0;
}
printf("\n\nde_payload = %s,ret = %d\n", de_payload, ret);
}
else
{
return 0;
}
Json::Value command;
Json::Reader read;
read.parse((char *)de_payload, (char *)de_payload + ret, command);
std::cout << command <<std::endl;
}
return 0;
}
int Websocket_Request::fetch_websocket_info(char *msg)
{
int pos = 0;
fetch_fin(msg, pos);
fetch_opcode(msg, pos);
fetch_mask(msg, pos);
fetch_payload_length(msg, pos);
fetch_masking_key(msg, pos);
fetch_payload(msg, pos);
return websockettoh5(payload_, payload_length_, fd_);
}
void Websocket_Request::reset()
{
fin_ = 0;
opcode_ = 0;
mask_ = 0;
memset(masking_key_, 0, sizeof(masking_key_));
payload_length_ = 0;
memset(payload_, 0, sizeof(payload_));
}
int Websocket_Request::fetch_fin(char *msg, int &pos)
{
fin_ = (unsigned char)msg[pos] >> 7;
return 0;
}
int Websocket_Request::fetch_opcode(char *msg, int &pos)
{
opcode_ = msg[pos] & 0x0f;
pos++;
return 0;
}
int Websocket_Request::fetch_mask(char *msg, int &pos)
{
mask_ = (unsigned char)msg[pos] >> 7;
return 0;
}
int Websocket_Request::fetch_masking_key(char *msg, int &pos)
{
if(mask_ != 1)
return 0;
for(int i = 0; i < 4; i++)
masking_key_[i] = msg[pos + i];
pos += 4;
return 0;
}
int Websocket_Request::fetch_payload_length(char *msg, int &pos)
{
payload_length_ = msg[pos] & 0x7f;
pos++;
if(payload_length_ == 126)
{
uint16_t length = 0;
memcpy(&length, msg + pos, 2);
pos += 2;
payload_length_ = ntohs(length);
}
else if(payload_length_ == 127)
{
uint32_t length = 0;
memcpy(&length, msg + pos, 4);
pos += 4;
payload_length_ = ntohl(length);
}
return 0;
}
int Websocket_Request::fetch_payload(char *msg, int &pos)
{
memset(payload_, 0, sizeof(payload_));
if(mask_ != 1)
{
memcpy(payload_, msg + pos, payload_length_);
}
else
{
for(int i = 0; i < payload_length_; i++)
{
int j = i % 4;
payload_[i] = msg[pos + i] ^ masking_key_[j];
}
}
pos += payload_length_;
return 0;
}
void Websocket_Request::print()
{
DEBUG_LOG("WEBSOCKET PROTOCOL\n"
"FIN: %d\n"
"OPCODE: %d\n"
"MASK: %d\n"
"PAYLOADLEN: %d\n"
"PAYLOAD: %s",
fin_, opcode_, mask_, payload_length_, payload_);
reset();
}
//
#ifndef __WEBSOCKET_REQUEST__
#define __WEBSOCKET_REQUEST__
#include <stdint.h>
#include "debug_log.h"
#include <DL_AES.h>
class Websocket_Request
{
public:
Websocket_Request() {};
Websocket_Request(int fd);
~Websocket_Request() {};
int fetch_websocket_info(char *msg);
void runconfigdata(char* str, int len, int socket);
void rungamedata(char* str, int len, int socket);
void print();
void reset();
int websockettoh5(char *content, int length,int fd);
private:
int fetch_fin(char *msg, int &pos);
int fetch_opcode(char *msg, int &pos);
int fetch_mask(char *msg, int &pos);
int fetch_masking_key(char *msg, int &pos);
int fetch_payload_length(char *msg, int &pos);
int fetch_payload(char *msg, int &pos);
private:
DL_AES _M_h5aes;
uint8_t fin_;
uint8_t opcode_;
uint8_t mask_;
uint8_t masking_key_[4];
uint64_t payload_length_;
char payload_[2048];
int fd_;
};
#endif
//以下这个类的话,主要用来回复客户端。
#include "websocket_respond.h"
#include "websocket_handler.h"
#include <json/json.h>
void Websocket_Respond::respondClient(int sockClient, int state, int type, int info, bool finalFragment)
{
Json::Value _M_reply;
_M_reply["state"] = state;
_M_reply["gcode"] = type;
if (info == 1)
{
_M_reply["type"] = "configData";
}
else if(info == 2)
{
_M_reply["type"] = "gameData";
}
Json::FastWriter fast;
std::string str = fast.write(_M_reply);
DL_AES dlaes;
dlaes.setkey((const char*)"DlClientPost2019");
unsigned char* _ect;
char* _base64;
int len = dlaes.encrypt((unsigned char*)str.c_str(), str.length(),&_ect);
int length = dlaes.base64_encode(_ect, len, &_base64);
int realDateLength = 0;
if(length < 126)
{
realDateLength = length + 2;
}
else if(length < 65536)
{
realDateLength = length + 4;
}
else
{
realDateLength = length + 10;
}
unsigned char* buf = (unsigned char*)malloc(realDateLength);;
char* charbuf = (char*)malloc(realDateLength);
int first = 0x00;
int tmp = 0;
if(finalFragment)
{
first = first + 0x80;
first = first + 0x1;
}
buf[0] = first;
tmp = 1;
unsigned int nuNum = (unsigned)length;
if(length < 126)
{
buf[1] = length;
tmp = 2;
}
else if (length < 65536)
{
buf[1] = 126;
buf[2] = nuNum >> 8;
buf[3] = length & 0xFF;
tmp = 4;
}
else
{
buf[1] = 127;
buf[2] = 0;
buf[3] = 0;
buf[4] = 0;
buf[5] = 0;
buf[6] = nuNum >> 24;
buf[7] = nuNum >> 16;
buf[8] = nuNum >> 8;
buf[9] = nuNum & 0xFF;
tmp = 10;
}
for(int i = 0; i < length; i++)
{
buf[tmp + i] = _base64[i];
}
memcpy(charbuf, buf, realDateLength);
send(sockClient, charbuf, realDateLength, 0);
}
//
#ifndef __WEBSOCKET_RESPOND__
#define __WEBSOCKET_RESPOND__
class Websocket_Respond
{
public:
Websocket_Respond() {};
~Websocket_Respond() {};
public:
void respondClient(int sockClient, int state, int type, int info, bool finalFragment);
};
#endif
|