Websocket服务器响应包,自己实现的WebSocket服务器数据包处理函数

最近在写WebSocket的服务器,打算同时做基于websocket的游戏及游戏服务器。研究了一下WebSocket协议,然后基于epoll写了一个websocket的服务器,可支持超大并发量^_^,这儿向大家提供数据包解析和创建的函数,供大家学习参考。

功能参考RFC 6455 ,目前最新的websocket v13版本的协议写成。支持mask和非mask两种方式,支持解析和创建数据长度在6K以下的WebSocket数据包。

这儿只是个解析示例,现实的网络开发中应使用流解析方式生成,流方式的实现即通过向一个状态机添加缓冲区,当状态机组合出一个包头时回调。

//websocket.h

/**

* WebSocket数据包解析和生成函数,RFC 6455 WebSocket V13 标准

* @author Hoverlees http://www.hoverlees.com

*/

#ifndef __HOVERLEES_WEBSOCKET_H

#define __HOVERLEES_WEBSOCKET_H

#define OPCODE_CONTINUATION0

#define OPCODE_TEXT1

#define OPCODE_BINARY2

#define OPCODE_CLOSE8

#define OPCODE_PING9

#define OPCODE_PONG10

typedef struct WebSocketPacket{

unsigned char fin;

unsigned char mask;

unsigned char opcode;

unsigned char mask_key[4];

int data_len;

unsigned char* data;

}WebSocketPacket;

int websocket_packet_parse(unsigned char* mem,int len,WebSocketPacket* packet,int data_len);

int websocket_packet_build(unsigned char* data,int len,WebSocketPacket* packet);

#endif

//websocket.c

/**

* 解析WebSocket数据包 ,参考RFC 6455 page27

* http://tools.ietf.org/html/rfc6455#page-27

* @param mem 数据包内存

* @param len 数据包长度

* @param packet 解析后的数据将存到这个对象中,请在传入packet之前初始化packet的data指针指向一块可用内存.

* @param data_len packet的内存块可接收的最大字节数

* @return 如果解析成功返回1,解析失败返回0

*/

int websocket_packet_parse(unsigned char* mem,int len,WebSocketPacket* packet,int data_len){

int i,j;

int pos;

pos=2;

i=mem[1]&127;

if(i==127){

//大于65536的数据包不适合用这种解析方式。应该使用流解析方式。

return 0;

}

else if(i==126){

i=mem[2]*256+mem[3];

pos=4;

}

if(i>data_len) return i-data_len;

packet->fin=(mem[0]&128) ? 1:0;

packet->opcode=mem[0]&0xf;

packet->mask=mem[1]&128;

packet->data_len=i;

if(packet->mask){

for(i=0;i<4;i++){

packet->mask_key[i]=mem[pos+i];

}

pos+=4;

for(i=0;idata_len;i++){

j=i%4;

packet->data[i]=mem[pos+i]^packet->mask_key[j];

}

}

else{

for(i=0;idata_len;i++){

packet->data[i]=mem[pos+i];

}

}

packet->data[i]=0;

return 1;

}

/**

* 创建数据包

* @param data 要发送的数据实体

* @param len 数据长度

* @param packet 数据包,生成的数据在数据包的data中,传入前请先初始化data指针以及需要的参数

* @return 最终生成的块大小

*/

int websocket_packet_build(unsigned char* data,int len,WebSocketPacket* packet){

int pos=0;

int i,j;

if(len>65528) return 0;

packet->data[0]=packet->fin? 128:0;

packet->data[0]|=packet->opcode;

if(len>=126){

packet->data[1]=126;

packet->data[2]=(len>>8)&0xFF;

packet->data[3]=len&0xFF;

pos=4;

}

else{

packet->data[1]=len&0xFF;

pos=2;

}

packet->mask=0; //为了支持稍老一点的浏览器

if(packet->mask){

packet->data[1]|=128;

for(i=0;i<4;i++){

packet->data[pos+i]=packet->mask_key[i];

}

pos+=4;

for(i=0;i

j=i%4;

packet->data[pos+i]=data[i]^packet->mask_key[j];

}

}

else{

for(i=0;i

packet->data[pos+i]=data[i];

}

}

pos+=len;

return pos;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值