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. 0428css样式

    CSS样式表|-引入的三种方式|--内联样式|----标签内部(空格style)|--内嵌样式|----<head></head>标签内部(<style></ ...

  2. Python3 数据结构

    列表 Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和元组不能. 以下是 Python 中列表的方法: 方法 描述 list.append(x ...

  3. OBJ文件格式分析工具: objdump, nm,ar

    首先简要阐述关于gcc.glibc和 binutils模块之间的关系 一.关于gcc.glibc和binutils模块之间的关系 1.gcc(gnu collect compiler)是一组编译工具的 ...

  4. 前端CSS技术全解(一)

    一.概述 1)用HTML完成样式工作 哪个标签有哪个属性难以记忆 需求变更影响较大(例如像修改成功法则以下的文字颜色需要修改4个地方) <h1 align="center"& ...

  5. Cassandra User 问题汇总(1)------------repair

    Cassandra Repair 问题 问1: 文档建议每周或者每月跑一次full repair.那么如果我是使用partition rangerepair,是否还有必要在cluster的每个节点上定 ...

  6. PGM:图模型学习概述

    http://blog.csdn.net/pipisorry/article/details/52571640 动机 前面我们讨论的问题出发点是给定一个图模型.如在独立性和推理讨论中,假定模型--结构 ...

  7. Apache shiro集群实现 (六)分布式集群系统下的高可用session解决方案---Session共享

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  8. 与markdown的第一次接触

    什么是markdown markdown是一种比html轻量级的标记语言. markdown的介绍与学习请参考:markdown认识与入门 CSDN Markdown博客视频教程 知乎: 怎样引导新手 ...

  9. Dynamics CRM 非声明验证方式下连接组织服务的两种方式的性能测试

    今天看了勇哥的博文"http://luoyong0201.blog.163.com/blog/static/1129305201510153391392/",又认识到了一种新的连接 ...

  10. EBS各个应用简称

     模块全称 Banking Center 模块简称 FPT 服务器目录 FPT_TOP Billing Connect CUE CUE_TOP CADView-3D DDD DDD_TOP CPG ...