高性能C++网络库libtnet实现:http
HTTP
libtnet提供了简单的http支持,使用也很简单。
一个简单的http server:
void onHandler(const HttpConnectionPtr_t& conn, const HttpRequest& request)
{
HttpResponse resp;
resp.statusCode = 200;
resp.setContentType("text/html");
resp.body.append("Hello World");
conn->send(resp);
}
TcpServer s;
HttpServer httpd(&s);
httpd.setHttpCallback("/test", std::bind(&onHandler, _1, _2));
httpd.listen(Address(80));
s.start(4);
我们对http server的"/test"注册了一个handler,当用户访问该url的时候,就会显示"Hello World"。
同样,http client的使用也很简单:
void onResponse(IOLoop* loop, const HttpResponse& resp)
{
cout << resp.body << endl;
loop->stop();
}
IOLoop loop;
HttpClientPtr_t client = std::make_shared<HttpClient>(&loop);
client->request("http://127.0.0.1:80/test", std::bind(&onResponse, &loop, _1));
loop.start();
这里,我们使用了一个http client,向server请求"/test"的内容,当服务器有响应之后,会调用响应的回调函数。
HTTP Parser
对于http的解析,我采用的是http parser,因为它采用的是流式解析,同时非常容易集成进libtnet。
使用http parser只需要设置相应的回调函数即可。http parser有如下几种回调:
- message begin,解析开始的时候调用
- url,解析url的时候调用
- status complete,http response解析status的时候调用
- header field,解析http header的field调用
- header value,解析http header的value调用
- headers complete,解析完成http header调用
- body,解析http body调用
- message complete,解析完成调用
这里特别需要注意的是http header的解析,因为http parser将其拆分成了两种回调,所以我们在处理的时候需要记录上一次header callback是field的还是value的。在解析field的时候,如果上一次是value callback,那我们就需要将上一次解析的field和value保存下来,而该次的解析则是一个新的field了。
另外,http parser还提供了upgrade的支持,所以我们很方便的就能区分该次请求是否为websocket。
Websocket
libtnet也提供了websocket的支持,现阶段,只支持RFC6455。
当libtnet通过http parser发现该次请求为websocket的时候,就进入了websocket的流程。websocket的使用也很简单,当握手成功之后,后续的所有通讯就是纯粹的tcp通信了。
一个简单的websocket server:
void onWsCallback(const WsConnectionPtr_t& conn, WsEvent event, const void* context)
{
switch(event)
{
case Ws_CloseEvent:
break;
case Ws_MessageEvent:
{
const string& str = *(const string*)context;
conn->send(str);
}
break;
case Ws_PongEvent:
break;
default:
break;
}
}
TcpServer s;
HttpServer httpd(&s);
httpd.setWsCallback("/push/ws", std::bind(&onWsCallback, _1, _2, _3));
httpd.listen(Address(80));
s.start();
可以看到,websocket的callback机制也类似于libtnet connection的callback机制,用户需通过event + context的方式来处理该次回调的数据。
libtnet对websocket的frame的处理参照的是tornado的websocket模块。也能够组合多frame的数据,外部只需要关注Ws_MessageEvent即可。
websocket client的实现也很简单:
void onWsConnEvent(const WsConnectionPtr_t& conn, WsEvent event, const void* context)
{
switch(event)
{
case Ws_OpenEvent:
conn->send("Hello world");
break;
case Ws_MessageEvent:
{
const string& msg = *(const string*)context;
LOG_INFO("message %s", msg.c_str());
conn->close();
}
break;
default:
break;
}
}
IOLoop loop;
WsClientPtr_t client = std::make_shared<WsClient>(&loop);
client->connect("ws://127.0.0.1:80/push/ws", std::bind(&onWsConnEvent, _1, _2, _3));
loop.start();
libtnet的地址https://github.com/siddontang/libtnet,欢迎围观。
高性能C++网络库libtnet实现:http的更多相关文章
- 高性能C++网络库libtnet实现:Connection
Connection libtnet只支持IPv4 TCP Connection,之所以这么做都是为了使得实现尽可能的简单.我们主要在Connection类中封装了对tcp连接的操作. Connect ...
- 高性能C++网络库libtnet实践:comet单机百万连接挂载测试
最近在用go语言做一个挂载大量长连接的推送服务器,虽然已经完成,但是内存占用情况让我不怎么满意,于是考虑使用libtnet来重新实现一个.后续我会使用comet来表明推送服务器. 对于comet来说, ...
- 高性能C++网络库libtnet实现:IOLoop
IOLoop libtnet采用的是prefork + event loop的架构方式,prefork就是server在启动的时候预先fork多个子进程同时工作,而event loop则是基于epol ...
- 发布一个参考tornado的高性能c++网络库:libtnet
libtnet是一个用c++编写的高性能网络库,它在设计上面主要参考tornado,为服务端网络编程提供简洁而高效的接口,非常易于使用. Echo Server void onConnEvent(co ...
- 专注于HTTP的高性能高易用性网络库:Fslib.network库
博客列表页:http://blog.fishlee.net/tag/fslib-network/ 原创FSLib.Network库(目前专注于HTTP的高性能高易用性网络库) FSLib.Networ ...
- [开源] gnet: 一个轻量级且高性能的 Golang 网络库
Github 主页 https://github.com/panjf2000/gnet 欢迎大家围观~~,目前还在持续更新,感兴趣的话可以 star 一下暗中观察哦. 简介 gnet 是一个基于 Ev ...
- Cowboy 开源 WebSocket 网络库
Cowboy.WebSockets 是一个托管在 GitHub 上的基于 .NET/C# 实现的开源 WebSocket 网络库,其完整的实现了 RFC 6455 (The WebSocket Pro ...
- 开源免费的C/C++网络库(c/c++ sockets library)
(1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html (2)Asio Asio基于Boo ...
- poco网络库分析,教你如何学习使用开源库
Poco::Net库中有 FTPClient HTML HTTP HTTPClient HTTPServer ICMP Logging Mail Messages NetCore NTP OAuth ...
随机推荐
- 关于spring的IOC和DI的xml以及注解的简单介绍
xml 一 目的:通过ApplicationContext对象的getBean方法获取所需类的对象. 编写一个service类 public class service { private Strin ...
- 在MPAndroidChart库K线图的基础上画均线
CombinedChart 可以直接使用MPAndroidChart库里面提供的CombinedChart实现组合图形 Demo:CombinedChartDemo ------分割线(如果想在一个图 ...
- 针对于Python的OpenCV环境搭建
OpenCV 依赖 下载OpenCV 配置 总结 给Python搭建opencv的环境还真是略嫌麻烦,于是做下笔记,以备不时之需. OpenCV 依赖 opencv有些依赖,我们必须安装一下,否则接下 ...
- linux中 probe函数的何时调用的?
点击打开链接 linux中 probe函数何时调用的 所以的驱动教程上都说:只有设备和驱动的名字匹配,BUS就会调用驱动的probe函数,但是有时我们要看看probe函数里面到底做了什么,还有传递给p ...
- spark下使用submit提交任务后报jar包已存在错误
使用spark submit进行任务提交,离线跑数据,提交后的一段时间内可以application可以正常运行.过了一段时间后,就抛出以下错误: org.apache.spark.SparkExcep ...
- RxJava操作符(04-过滤操作)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51656494 本文出自:[openXu的博客] 目录: Debounce Distinct ...
- React Native组件只Image
不管在Android还是在ios原生的开发中,图片都是作为控件给出来的,在RN中也有这么一个控件(Image).根据官网的资料,图片分为本地静态图片,网络图片和混合app资源.一下分类介绍来源官网. ...
- Erlang递归列举目录下文件
Erlang递归列举目录下文件(金庆的专栏)%%%-------------------------------------------------------------------%%% @aut ...
- FFmpeg的H.264解码器源代码简单分析:熵解码(Entropy Decoding)部分
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
- 有N个数,组成的字符串,如012345,求出字串和取MOD3==0的子串,如012 12 123 45。
#include <iostream> using namespace std; int getSum(string str, int begin, int len) { int sum ...