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的更多相关文章

  1. 高性能C++网络库libtnet实现:Connection

    Connection libtnet只支持IPv4 TCP Connection,之所以这么做都是为了使得实现尽可能的简单.我们主要在Connection类中封装了对tcp连接的操作. Connect ...

  2. 高性能C++网络库libtnet实践:comet单机百万连接挂载测试

    最近在用go语言做一个挂载大量长连接的推送服务器,虽然已经完成,但是内存占用情况让我不怎么满意,于是考虑使用libtnet来重新实现一个.后续我会使用comet来表明推送服务器. 对于comet来说, ...

  3. 高性能C++网络库libtnet实现:IOLoop

    IOLoop libtnet采用的是prefork + event loop的架构方式,prefork就是server在启动的时候预先fork多个子进程同时工作,而event loop则是基于epol ...

  4. 发布一个参考tornado的高性能c++网络库:libtnet

    libtnet是一个用c++编写的高性能网络库,它在设计上面主要参考tornado,为服务端网络编程提供简洁而高效的接口,非常易于使用. Echo Server void onConnEvent(co ...

  5. 专注于HTTP的高性能高易用性网络库:Fslib.network库

    博客列表页:http://blog.fishlee.net/tag/fslib-network/ 原创FSLib.Network库(目前专注于HTTP的高性能高易用性网络库) FSLib.Networ ...

  6. [开源] gnet: 一个轻量级且高性能的 Golang 网络库

    Github 主页 https://github.com/panjf2000/gnet 欢迎大家围观~~,目前还在持续更新,感兴趣的话可以 star 一下暗中观察哦. 简介 gnet 是一个基于 Ev ...

  7. Cowboy 开源 WebSocket 网络库

    Cowboy.WebSockets 是一个托管在 GitHub 上的基于 .NET/C# 实现的开源 WebSocket 网络库,其完整的实现了 RFC 6455 (The WebSocket Pro ...

  8. 开源免费的C/C++网络库(c/c++ sockets library)

    (1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html (2)Asio Asio基于Boo ...

  9. poco网络库分析,教你如何学习使用开源库

    Poco::Net库中有 FTPClient HTML HTTP HTTPClient HTTPServer ICMP Logging Mail Messages NetCore NTP OAuth ...

随机推荐

  1. How to Change Default Web ADI Upload Parameters for FlexField Import / Validation

    How to Change Default Web ADI Upload Parameters for FlexField Import / Validation (文档 ID 553345.1) 转 ...

  2. JVM:类的生命周期

    类的生命周期 综述 1.    只有当一个类被切实使用到的时候才会被加载到虚拟机中(例如:new, 方法调用, A a = null;不算) 2.    若在加载一个类的过程中,有其他类被切实使用到, ...

  3. hive分区partition(动态和静态分区混合使用; partition的简介)

    分区是hive存放数据的一种方式.将列值作为目录来存放数据,就是一个分区.这样where中给出列值时,只需根据列值直接扫描对应目录下的数据,不扫面其他不关心的分区,快速定位,查询节省大量时间.分动态和 ...

  4. 关于bitmap你不知道的一些事

    1.计算机表示图形的几种方式 1)BMP :几乎不进行压缩 占用空间比较大 2)JPG : 在BMP的基础上对相邻的像素进行压缩,占用空间比BMP小 3) PNG : 在JPG的基础上进一步压缩 占用 ...

  5. Android简易实战教程--第三十九话《简单的模糊查询》

    今天这一篇小案例模拟模糊查询,即输入一个字符,显示手机对应的所有存在该字符的路径. 布局: <?xml version="1.0" encoding="utf-8& ...

  6. Swift3中如何为Array写一个限定Type的扩展

    我们知道Swift可以扩展已存在的类或结构,这些类或结构可以存在于标准库(或称为核心库)中.如果结构是一个集合类型(比如Array)就更有趣了.我们想尝试写一个限定Type数组的扩展,So我们就拿Ar ...

  7. React Native自定义导航条

    Navigator和NavigatorIOS 在开发中,需要实现多个界面的切换,这时候就需要一个导航控制器来进行各种效果的切换.在React Native中RN为我们提供了两个组件:Navigator ...

  8. PHP 文件下载 浅析

    无控制类型 avi文件 rar文件 mp4MP3图片等会被直接解析 核心代码 类型 长度 实现函数 优化 原始下载文件的名称 优化后的文件下载名称 总结 文件下载的功能对一个网站而言基本上是必备的了, ...

  9. [Python]print vs sys.stdout.write

    之前只是在项目中看到过,没怎么注意,正好跟对象一起看python学习手册,看到了这个部分于是来研究下. python版本 2.7.x os  win7 print  一般就是执行脚本的时候,把信息直接 ...

  10. 使用Myeclipse10.0自动生成搭建SSH框架(数据库表自动反向转换成Hibernate实体)实现用户登陆

    我这里使用的数据库是mysql5.0 数据是上课用的.这些都不是重点,重要的是学会这个方法: 创建好数据库: create database jboadefault character set utf ...