HTML5应用越来越多了,应朋友要求写了一个小应用框架
时间:2010-08-03
来源:互联网
- /*
- * SendBuf.h
- *
- * Created on: 2010-8-2
- * Author: zliming
- */
-
- #ifndef SENDBUF_H_
- #define SENDBUF_H_
-
- #include <vector>
-
- using namespace std;
-
- /*
- * tr1/shared_ptr.h在mingw下怪怪,又不想用boost,头太大
- */
-
- class SharedBuf {
- public:
- SharedBuf(const char* data);
- SharedBuf(const SharedBuf& o);
- ~SharedBuf();
- void operator=(const SharedBuf& o);
- size_t Size();
- const char* GetBuffer();
-
- private:
- void ReleaseRef();
- private:
- struct Data {
- char* data;
- int refCount;
- size_t len;
- } *ptr;
- };
-
- #endif /* SENDBUF_H_ */
- /*
- * SendBuf.cpp
- *
- * Created on: 2010-8-2
- * Author: zliming
- */
-
- #include "SendBuf.h"
- #include <string.h>
-
- SharedBuf::SharedBuf(const char* buf) {
- size_t len = strlen(buf);
- ptr = new Data;
- ptr->len = len + 2;
- ptr->data = new char[ptr->len];
- ptr->data[0] = 0;
- memcpy(ptr->data + 1, buf, len);
- ptr->data[len + 1] = 0xff;
- ptr->refCount = 1;
- }
- SharedBuf::SharedBuf(const SharedBuf& o): ptr(0){
- operator=(o);
- }
- SharedBuf::~SharedBuf(){
- ReleaseRef();
- }
- size_t SharedBuf::Size(){
- if(ptr){
- return ptr->len;
- }
- return 0;
- }
- const char* SharedBuf::GetBuffer(){
- if(ptr){
- return ptr->data;
- }
- return NULL;
- }
- void SharedBuf::operator =(const SharedBuf& o){
- //去掉原引用的内存
- ReleaseRef();
- ptr = o.ptr;
- ptr->refCount ++;
- }
- void SharedBuf::ReleaseRef(){
- if(ptr && --ptr->refCount <= 0){
- delete[] ptr->data;
- delete ptr;
- ptr = 0;
- }
- }
- #ifndef __CLIENT_H__
- #define __CLIENT_H__
-
- #include <libZLM/LibZLM.h>
-
- struct SafeDelete
- {
- template <typename T>
- void operator ()(T& t)
- {
- if(t)
- {
- delete t;
- t = NULL;
- }
- }
- };
- #define SAFE_DELETE SafeDelete()
-
- class Client
- {
- public:
- virtual void Start() { }
- virtual ~Client() { }
- Socket& GetSocket(){ return _socket; }
-
- private:
- Socket _socket;
- };
-
- template<typename C>
- class Server
- {
- public:
- Server(int port) : _listen("0.0.0.0", port) { }
- virtual void Accept(const Error& ec, C* client)
- {
- if(client)
- {
- if(!ec)
- client->Start();
- else
- delete client;
- }
- client = new C;
- _listen.AsyncAccept(&client->GetSocket(), Bind(&Server::Accept, this, _1, client));
- }
- virtual ~Server(){}
- protected:
- Listen _listen;
- };
-
- #endif//__CLIENT_H__
- /*
- * websocket.h
- *
- * Created on: 2010-7-29
- * Author: zliming
- */
-
- #ifndef WEBSOCKET_H_
- #define WEBSOCKET_H_
-
- #include "Socket.h"
-
- class WebSocket : public Client {
- public:
- void Start();
- virtual void DoCommand(Record& record);
-
- private:
- void Do(const Error& err, int len);
- void OnRead(const Error& err, int len);
-
- private:
- char buf[0x8000];
- size_t read_bytes;
- int step;
- char* buf_offset;
- };
-
- #endif /* WEBSOCKET_H_ */
- //============================================================================
- // Name : websocket.cpp
- // Author : zliming
- //============================================================================
-
- #include "websocket.h"
- #include "Handshaker.h"
- #include <stdlib.h>
- #include <string.h>
- #include <memory.h>
- #include <stdio.h>
- #include <string>
- using namespace std;
-
- static char flash_policy_req[] = "<policy-file-request/>";
- static char flash_policy_ret[] = "<cross-domain-policy>\n"
- "<allow-access-from domain='*' to-ports='*'/>\n"
- "</cross-domain-policy>";
- static char http_end_flag[] = "\r\n\r\n";
-
- void WebSocket::Start() {
- step = 1;
- read_bytes = 0;
- Do(Error(), 0);
- }
-
- void WebSocket::Do(const Error& err, int len) {
- switch (step) {
- case 1:
- step = 2;
- return GetSocket().AsyncRead(buf, sizeof(flash_policy_req), Bind(
- &WebSocket::Do, this, _1, _2));
- case 2:
- //如果是通过Flash桥来连接的,会先读求连接策略
- if (memcmp(flash_policy_req, buf, sizeof(flash_policy_req)) == 0) {
- step = 3;
- return GetSocket().AsyncWrite(flash_policy_ret,
- sizeof(flash_policy_ret),
- Bind(&WebSocket::Do, this, _1, _2));
- case 3:
- return delete this;
- } else {
- case 4:
- read_bytes += len;
- buf[read_bytes] = 0;
- buf_offset = strstr(buf, http_end_flag);
- if (buf_offset) {
- //HTTP头读完,还要读8个字节(key3)
- if (buf + read_bytes - (buf_offset + 4) < 8) {
- step = 5;
- return GetSocket().AsyncRead(buf + read_bytes, 8 - (buf
- + read_bytes - (buf_offset + 4)), Bind(
- &WebSocket::Do, this, _1, _2));
- case 5:
- read_bytes += len;
- buf[read_bytes] = 0;
- }
- //全体需要的数据完成
- Handshaker handshaker(buf, read_bytes);
- const string& result = handshaker.GetResult();
- if(result.empty()){
- return delete this;
- }
- memcpy(buf, result.c_str(), result.length());
- memcpy(buf + result.length(), handshaker.GetChallenge(), 16);
-
- read_bytes = 0;
- return GetSocket().AsyncWrite(buf, result.length() + 16,
- Bind(&WebSocket::OnRead, this, _1, 0));
- } else {
- step = 4;
- return GetSocket().AsyncReadSome(buf + read_bytes, sizeof(buf)
- - read_bytes - 1, Bind(&WebSocket::Do, this, _1, _2));
- }
- }
- }
- }
- void WebSocket::OnRead(const Error& err, int len){
- if(!err){
- read_bytes += len;
- char* find, *prog = buf;
- while((find = (char*)memchr(prog, 0xff, buf + read_bytes - prog)) != NULL){
- //websocket发送的数据为: 00 data ff
- *find = 0;
- //这个是Json数据的操作类,和javascript通讯,json是不二选择
- Record record;
- if(record.FromString(prog + 1, find - prog - 1)){
- this->DoCommand(record);
- }
- //处理完成,跳过已经处理部分数据
- prog = find + 1;
- }
- if(prog != buf){
- //已经处理完的数据丢弃
- memmove(buf, prog, buf + read_bytes - prog);
- read_bytes = buf + read_bytes - prog;
- }
- if(sizeof(buf) - read_bytes - 1 > 0){
- //读新的数据进来
- return GetSocket().AsyncReadSome(buf + read_bytes,
- sizeof(buf) - read_bytes - 1,
- Bind(&WebSocket::OnRead, this, _1, _2));
- }
- }
- delete this;
- }
- void WebSocket::DoCommand(Record& record){
-
- }
作者: zliming 发布时间: 2010-08-03
- /*
- * Handshaker.h
- *
- * Created on: 2010-7-29
- * Author: zliming
- */
-
- #ifndef HANDSHAKER_H_
- #define HANDSHAKER_H_
-
- #include <string>
- using namespace std;
-
- class Handshaker{
- public:
- const string& GetResult();
- const char* GetChallenge();
- Handshaker(char* req, size_t req_len);
-
- private:
- string GetValue(const char* key);
- unsigned GetNumber(const char* value);
- private:
- string result;
- char* req;
- unsigned char challenge[16];
- };
-
- #endif /* HANDSHAKER_H_ */
- /*
- * Handshaker.cpp
- *
- * Created on: 2010-7-29
- * Author: zliming
- */
-
- #include "Handshaker.h"
- #include "md5.h"
- #include <string.h>
- #include <stdio.h>
- #include <algorithm>
-
- unsigned BigEndian(unsigned i){
- return (i << 24) | (i >> 24) |
- ((i & 0xff00) << 8) | ((i & 0xff0000) >> 8);
- }
-
- Handshaker::Handshaker(char* req, size_t req_len){
- this->req = req;
- //必须是GET请求
- if(memcmp(req, "GET", strlen("GET")) != 0 ||
- GetValue("Upgrade:") != "websocket" ||
- GetValue("Connection:")!= "upgrade"){
- return;
- }
- string origin = GetValue("Origin:");
- string key1 = GetValue("Sec-WebSocket-Key1:");
- string key2 = GetValue("Sec-WebSocket-Key2:");
- if(origin.empty() || key1.empty() || key2.empty()){
- return;
- }
- char* key3 = req + req_len - 8;
- string uri(req + 4, strchr(req + 4, ' ') - (req + 4));
- string location = "ws://" + GetValue("Host:") + uri;
- unsigned n1 = GetNumber(key1.c_str());
- unsigned n2 = GetNumber(key2.c_str());
- unsigned sc1 = count(key1.begin(), key1.end(), ' ');
- unsigned sc2 = count(key2.begin(), key2.end(), ' ');
- if(sc1 == 0 || sc2 == 0 || n1 % sc1 != 0 || n2 % sc2 != 0){
- return;
- }
- unsigned part1 = BigEndian(n1 / sc1);
- unsigned part2 = BigEndian(n2 / sc2);
- memcpy(challenge, &part1, sizeof(unsigned));
- memcpy(challenge + sizeof(unsigned), &part2, sizeof(unsigned));
- memcpy(challenge + sizeof(unsigned) * 2, key3, 8);
- MD5_CTX ctx;
- MD5_Init(&ctx);
- MD5_Update(&ctx, challenge, sizeof(challenge));
- MD5_Final(challenge, &ctx);
-
- //返回
- result ="HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Location: " + location + "\r\n"
- "Sec-WebSocket-Origin: " + origin + "\r\n";
-
- string proto = GetValue("Sec-WebSocket-Protocol:");
- if(!proto.empty()){
- result += "Sec-WebSocket-Protocol: " + proto + "\r\n";
- }
- result += "\r\n";
- }
-
- const char* Handshaker::GetChallenge(){
- return (const char*)challenge;
- }
-
- const string& Handshaker::GetResult(){
- return result;
- }
-
- unsigned Handshaker::GetNumber(const char* value){
- unsigned ret = 0;
- while(*value){
- if(*value >= '0' && *value <= '9'){
- ret = ret * 10 + *value - '0';
- }
- value++;
- }
- return ret;
- }
-
- string Handshaker::GetValue(const char* key){
- string ret;
- char* find = strstr(req, key);
- if(find){
- size_t len = strlen(key);
- find += len + 1;
- ret.append(find, strchr(find, '\r') - find);
- transform(ret.begin(), ret.end(), ret.begin(), ::tolower);
- }
- return ret;
- }
- /*
- * Chat.h
- *
- * Created on: 2010-8-1
- * Author: zliming
- */
-
- #ifndef CHAT_H_
- #define CHAT_H_
-
- #include "websocket.h"
- #include "SendBuf.h"
- #include <string>
-
- class Chat : public WebSocket {
- public:
- void DoCommand(Record& record);
- void SendChat(SharedBuf chat);
- ~Chat();
-
- private:
- void FinishSend(SharedBuf);
- private:
- string username;
- };
-
- #endif /* CHAT_H_ */
- /*
- * Chat.cpp
- *
- * Created on: 2010-8-1
- * Author: zliming
- */
-
- #include "Chat.h"
- #include <string.h>
- #include <map>
-
- //只有一个IORUN,不需要互斥
- map<string, Chat*> users;
-
- void Chat::DoCommand(Record& record) {
- if (memcmp("login", (const char*)record["cmd"], sizeof("login")) == 0) {
- Record ret;
- ret["cmd"] = "login";
- if (users.find((const char*) record["value"]) != users.end()) {
- ret["value"] = "user online";
- } else {
- ret["value"] = "ok";
- username = (const char*) record["value"];
- users[username] = this;
- }
- SharedBuf buf(ret.ToString());
- SendChat(buf);
- } else if (!username.empty() &&
- memcmp("chat", (const char*)record["cmd"], sizeof("chat")) == 0) {
- //用户在线,发聊天包时加上用户名
- record["user"] = username.c_str();
- SharedBuf buf(record.ToString());
- for (map<string, Chat*>::iterator it = users.begin(); it != users.end(); ++it) {
- it->second->SendChat(buf);
- }
- }
- }
- void Chat::SendChat(SharedBuf chat) {
- //在发送完成处理中引用这个SharedBuf,不让它过早释放
- GetSocket().AsyncWrite((char*)chat.GetBuffer(), chat.Size(),
- Bind(&Chat::FinishSend, this, chat));
- }
- void Chat::FinishSend(SharedBuf){
-
- }
- Chat::~Chat() {
- if(!username.empty()){
- users.erase(username);
- //通知用户下线
- Record ret;
- ret["cmd"] = "logout";
- ret["value"] = username.c_str();
- SharedBuf buf(ret.ToString());
- for (map<string, Chat*>::iterator it = users.begin(); it != users.end(); ++it) {
- it->second->SendChat(buf);
- }
- }
- }
作者: zliming 发布时间: 2010-08-03
http://zliming.3322.org/
作者: zliming 发布时间: 2010-08-03
什么应用的?能否给个说明
作者: zhanglistar 发布时间: 2010-08-03
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
作者: xiapan83 发布时间: 2010-08-03
这里用这个做一个聊天演示
作者: zliming 发布时间: 2010-08-03
作者: ecjtubaowp 发布时间: 2010-08-03
作者: zliming 发布时间: 2010-08-03
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28