How to write simple HTTP proxy with Boost.Asio

How to write simple HTTP proxy with Boost.Asio

Russian · English

In this article I describe process of writing of simple cross-platform HTTP proxy.

What we need

To develop this example (source code) I used Boost version 1.35. To build example, you can use cmake (but you can also build sources manually). To configure and build you need to run following commands (on Unix-like OSes)1:

> cmake .
> make

and after compilation you'll get proxy-asio-async executable, that you can run from command line. This program accepts only one argument — number of threads, that will perform request processing (by default, this value is equal 2). Port number on which requests will accepted is hardcoded in source code and equal to 100012.

Architecture

As in previous examples, our program consists from three parts:

  • the main function, that parses command line, creates separate threads for asio services together with server object, and then enters into request processing loop;
  • server class, that accepts requests, and creates connection object, that implements all logic of connection handling;
  • connection class, that implements all logic, and pass data between client & web-server.

The data processing is performed in asynchronous mode, and to distribute load between processors, we can use several independent asio services, that perform dispatching of calls (asio::io_service).

Note: Most hard part of the development of asynchronous code is proper design of data flow. I usually draw a state diagram and then transform each state to separate function. Presence of such diagram is very helpful for understanding of code by other developers.

Implementation

The main function is pretty simple, so we'll not analyze it — you can just look to its source code and understand, what it does (all common definitions are in file common.h.

Implementation of server (the server class — proxy-server.hpp & proxy-server.cpp) also not so much different from previous examples — changes were made only for method, that is used to select service, that will implement dispatching. In our example new service is selected from circular list of services, that allow us to get some load balancing for requests.

All data processing logic is implemented in connection class (proxy-conn.hpp & proxy-conn.cpp. I want to say, that parsing of headers was done without any optimisation3.

Data processing is started from call to start function from server class, that accepts connection and creates new object of connection class. This function initiates asynchronous reading of request headers from browser.

Reading of request headers is performed in the handle_browser_read_headers function, that is called when we get some part of data from browser. I need to mention, that if we get incomplete headers (there is no empty string (\r\n\r\n)), then this function initiates new reading of headers, trying to get them all.

After we get all headers, this function parses them and extracts version of HTTP protocol, used method and address of web-server (some of these data will be required to detect persistent connections).

After parsing of headers, this function calls start_connect, that parses address of web-server, and if we don't have opened connection to this server, then it initiates process of name resolution. If we have opened connection, then we simply start data transfer with start_write_to_server function.

The handle_resolve function is called after name resolution, and if we get address of server, then it initiates process of connection establishing. Result of this process is handled by handle_connect function, that initiates process of data transfer to the server with start_write_to_server function, that forms correct headers, and pass these data to the server.

After transferring data to server, in function handle_server_write we initiate reading of response (only headers first) from server. Processing of headers is handled by handle_server_read_headers function, that is similar to the handle_browser_read_headers, but it also tries to understand — should we close connection after data transfer, or not. After processing of headers, this function initiates process of sending data to browser.

After sending of headers, we create a loop, that transfer body of response from server to browser. In this loop we use two functions — handle_server_read_body and handle_browser_write, each of them calls another function until we don't finish reading of data from server (either number of bytes, specified in headers) or don't get end of file.

If we'll get end of file, then we'll pass rest of data to the browser and close connection. Or if we use persistent connection, then we'll pass control to the start function, that initiates reading of new headers from browser.

That's all. As I already mentioned above, main problem — building of right data flow sequence.


1. If cmake can't find required libraries, you can specify their location with two <em>cmake's variables — CMAKE_INCLUDE_PATH и CMAKE_LIBRARY_PATH, by running cmake following way:

> cmake . -DCMAKE_INCLUDE_PATH=~/exp/include -DCMAKE_LIBRARY_PATH=~/exp/lib

2. I could also implement code, that allow to specify port number in command line, but I was lazy, as this example was just a prototype to check some of my ideas.

3. There is also cpp-netlib project, that has (development in progress) parsers for basic protocols — HTTP, SMTP и т.п.

How to write simple HTTP proxy with Boost.Asio的更多相关文章

  1. 使用Boost.Asio编写通信程序

    摘要:本文通过形像而活泼的语言简单地介绍了Boost::asio库的使用,作为asio的一个入门介绍是非常合适的,可以给人一种新鲜的感觉,同时也能让体验到asio的主要内容. Boost.Asio是一 ...

  2. boost.asio包装类st_asio_wrapper开发教程(2013.12.8更新)(二)

    如果你是偶然浏览到这里,请先看 源代码及例程下载地址:命令行:svn checkout http://st-asio-wrapper.googlecode.com/svn/trunk/ st-asio ...

  3. c++ boost asio库初学习

    前些日子研究了一个c++的一个socket库,留下范例代码给以后自己参考. 同步server: // asio_server.cpp : コンソール アプリケーションのエントリ ポイントを定義します. ...

  4. 如何在多线程leader-follower模式下正确的使用boost::asio。

    #include <assert.h> #include <signal.h> #include <unistd.h> #include <iostream& ...

  5. BOOST.Asio——Tutorial

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  啥说的,鄙视那些无视版权随 ...

  6. BOOST.Asio——Overview

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  啥说的,鄙视那些无视版权随 ...

  7. boost asio sync

    Service: #include<boost/asio.hpp> #include<boost/thread.hpp> #include<iostream> #i ...

  8. 网络库crash以及boost asio strand dispath分析

    最近在做服务器的稳定性的相关测试,服务器的网络底层使用的是boost asio,然后自己做的二次封装以更好的满足需求. 服务器昨天晚上发现crash了一次,之前测试了将近半个多月,有一次是莫名的退出了 ...

  9. boost asio tcp server 拆分

    从官方给出的示例中对于 boost::asio::ip::tcp::acceptor 类的使用,是直接使用构造函数进行构造对象,这一种方法用来学习是一个不错的方式. 但是要用它来做项目却是不能够满足我 ...

随机推荐

  1. 浅谈初次搭建nginx+php+mysql遇到的问题

    先说明下我linux上的环境: nginx + php(5.5.10) + mysql 開始的源代码已经在本地写好,并调试成功(本地的环境是用XAMPP的默认配置).在把代码上传至linux上时,出现 ...

  2. delphi高手突破之异常及错误处理

    什么是异常?为什么要用它? 所谓“异常”是指一个异常类的对象.Delphi的VCL中,所有异常类都派生于Exception类.该类声明了异常的一般行为.性质.最重要的是,它有一个Message属性可以 ...

  3. SpringMVC 返回字符串

    今天看到一段代码,关于SpringMVC的Controller中返回字符串的代码,这段代码被我称为2b代码(英文名:2b Code). @RequestMapping(value="twoB ...

  4. 自定义navigationBar的高度

    原来看过一些解决办法,都不太好,最近解决自定义 tab bar的高度的问题,从中受到启发,找到下面的解决办法. 个人觉得和网上找到的其它方法比还是很简洁的. 关键是要调整navBarTransitio ...

  5. jquery-easyui实现页面布局和增删改查操作(SSH2框架支持)转载

    http://blessht.iteye.com/blog/1069749/ 已注册:ooip 关联的csdn 前几天心血来潮用jquery-easyui+spring.struts2.hiberna ...

  6. Expert for SQL Server 诊断系列

    Expert for SQL Server 诊断系列 Expert 诊断优化系列------------------锁是个大角色   前面几篇已经陆续从服务器的几个大块讲述了SQL SERVER数据库 ...

  7. Windows Azure 安全最佳实践 - 第 1 部分:深度解析挑战防御对策

    我每次与开发人员讨论将应用程序迁移到云时都围绕着两个主要问题. 1. 首先是业务.将应用程序迁移到云可以带来怎样的规模经济? 2. 其次是安全问题."云的安全性如何,尤其是Windows A ...

  8. iTextSharp使用字体设置摘录

    用iTextSharp做pdf转换的时候,需要添加水印.文字水印的时候,需要设置字体,查了下文档.摘录下解决方案. iText中输出中文,有三种方式: 1.使用iTextAsian.jar中的字体   ...

  9. Servlet过滤器——使用过滤器禁止浏览器缓存页面

    1.概述 IE缓存虽然能提高已储存网站的访问速度,但是过度的IE缓存会影响浏览器的响应速度.同时还可能为网站的运行带来一些不必要的麻烦.例如:可能会因为浏览器缓存的应用,而导致Web服务器不能准确的计 ...

  10. 解决 Android SDK Manager不能下载旧版本的sdk的问题

    解决无法使用Android SDK  Manager下载SDK开发包的解决办法. 当我们在官网下载google的集成ADT,也就是adt-bundle-linux-x86.zip开发包,进行解压, 打 ...