当前位置:首页 >> 编程开发 >> Visual C++ >> 内容

Muduo 网络编程示例(十)socks4a 代理服务器

时间:2015/5/19 21:32:03 作者:平凡之路 来源:xuhantao.com 浏览:

本文介绍用 muduo 实现一个简单的 socks4a 代理服务器,代码见 http://code.google.com/p/muduo/source/browse/trunk/examples/socks4a/ 。

TCP 中继器

在实现 socks4a proxy 之前,我们先写一个功能更简单的网络程序—— TCP 中继器 (TCP relay),或者叫做穷人的 tcpdump (poor man's tcpdump)。

一般情况下,客户端程序直接 连接服务端,如下图。有时候,我们想在 client 和 server 之间放一个中继器 (relay),把 client 与 server 之间的通信内容记录下来。这时用 tcpdump 是最方便省事的,但是 tcpdump 需要 root 权 限,万一没有 root 密码呢?穷人有穷人的办法,自己写一个 relay,让 client 连接 relay,再让 relay 连接 server,如下图中的 T 型结构,relay 扮演了类似 proxy 的角色。

TcpRelay 是我们自己写的,可以动动手脚。除了记录通信内容,还可以制造延时,或者故意 翻转 1 bit 数据以模拟 router 硬件故障。

TcpRelay 的功能(业务逻辑)看上去很简单,无 非是把连接 C 上收到的数据发给连接 S,同时把连接 S 上收到的数据发给连接 C。但仔细考虑起来, 细节其实不那么简单:

建立连接。为了真实模拟 client,TcpRelay 在 accept 连接 C 之后才向 server 发起连接 S,那 么在 S 建立起来之前,从 C 收到数据怎么办?要不要暂存起来?

并发连接的管理。上图中只画出了一个 client,实际上 TcpRelay 可以服务多个 clients,左右两 边这些并发连接如何管理,如何防止串话(cross talk)?

连接断开。Client 和 Server 都可能主动断开连接。当 Client 主动断开连接 C 时,TcpRelay 应 该立刻断开 S。当 Server 主动断开连接 S 时,TcpRelay 应立刻断开 C。这样才能比较精确地模拟 Client 和 Server 的行为。在关闭连接的刹那,又有新的 client 连接进来,复用了刚刚 close 的 fd 号码,会不会造成串话? 万一 Client 和 Server 几乎同时主动断开连接,TcpRelay 如何应对?

速度不匹配。如果连接 C 的带宽是 100KB/s,而连接 S 的带宽是 10MB/s,不巧 Server 是个 chargen 服务,会全速发送数据,那么会不会撑爆 TcpRelay 的 buffer?如何限速?特别是在使用 non-blocking IO 和 level-trigger polling 的时候如何限制读取数据的速度?

在看 muduo 的实现之前,请读者思考:如果用 Sockets API 来实现 TcpRelay,如何解决以上这些 问题。

TcpRelay 的实现很简单,只有几十行代码 http://code.google.com/p/muduo/source/browse/trunk/examples/socks4a/tcprelay.cc,主要逻辑 都在 Tunnel class 里

http://code.google.com/p/muduo/source/browse/trunk/examples/socks4a/tunnel.h 。这个 实现解决了前三个问题,第四个留给将来吧。

Socks4a 代理服务器

Socks4a 的功能与 TcpRelay 非常相似,也是把连接 C 上收到的数据发给连接 S,同时把连接 S 上收到的数据发给连接 C。它与 TcpRelay 的区别在于,TcpRelay 固定连到某个 server 地址,而 socks4a 允许 client 指 定要连哪个 server。在 accept 连接 C 之后,Socks4a server 会读几个字节,以了解 server 的地 址,再发起连接 S。

Socks4a 的协议非常简单,请参考维基百科 http://en.wikipedia.org/wiki/SOCKS#SOCKS_4a 。

muduo 的 socks4a 代理服务器的实现在 http://code.google.com/p/muduo/source/browse/trunk/examples/socks4a/socks4a.cc,它也使用了 Tunnel class。与 TcpRelay 相比,只多了解析 server 地址这一步骤。

muduo 这个 socks4a 是个标准的网络服务,可以供 Web 浏览器使用(我正是这么测试它的)。

n:1 与 1:n 连接转 发

云风在《写了一个 proxy 用途你懂的》中写了一个 TCP 隧道 tunnel,程序由三部分组成: n:1 连接转发服务,1:n 连接转发服务,socks 代理服务。

我仿照他的思路,用 muduo 实现了 这三个程序。不同的是,我没有做数据混淆,所以不能用来翻传说中的墙。

n:1 连接转发服务就是《Muduo 网络编程示例之七:“串并转换”连接服务器及其自动化测试》中 的 multiplexer (数据选择器)。

1:n 连接转发服务是该文提到的 backend,一个数据分配器(demultiplexer),代码在 http://code.google.com/p/muduo/source/browse/trunk/examples/multiplexer/demux.cc

socks 代理服务正是本文实现的 socks4a。

有兴趣的读者可以把这三个程序级联起来试一试。

Muduo 编程示例系列告一段落

《Muduo 网络编程示例》从今年2月初开始写,到今天正好是四个月,我写了十一篇博客,基本按计划 完成了任务。这个系列暂告一段落。

这个系列基本涵盖了 muduo 为编写单线程服务端和客户端 TCP 网络程序提供的功能,muduo 的能力不止于此:

多线程,muduo::net::TcpServer 内置了一个简单但适应性很强的线程模型。目前博客上的例子涉 及的业务逻辑很简单,没有复杂的运算,瓶颈通常在 IO 上,多线程的优势发挥不出来。

高级应用。比方说用 muduo::net::Channel 配合 signalfd 来处理信号;其他非阻塞网络客户端库 (例如 ZooKeeper 的 C 客户端,PostgreSQL 的客户端 libpq)与 muduo EventLoop 的集成。

以上两点在以后的文章里会提及,不会明珠暗藏。

Muduo 在 2010 年 8 月底发布 0.1.0 版 ,随着这个编程示例系列文章的发表,迄今已发布了 14 次小升级,下载地址: http://code.google.com/p/muduo/downloads/list

接下来的计划

接下来,我还会写一 系列博客,目前想到的有:

谈一谈我的网络编程学习经验。文章已经完成大半,端午节之后可以发布。

muduo 设计与实现系列,介绍如何一步步实现一个非阻塞网络库。代码已经准备得差不多了,在 https://github.com/chenshuo/recipes/tree/master/reactor

用 muduo 实现一些稍微复杂一些的网络程序,比如小规模的分布式系统。计划有:利用 Paxos 算 法实现一个高可用的 in-memory key value 存储,在此基础上实现 naming service,然后实现我以前 多次提到的简单机群管理系统等等。目前 muduo 的示例程序都是简单独立的网络程序,下半年我想多 写一写由多个程序组成的系统,具体谈一谈分布式系统细节设计。

查看本栏目更多精彩内容:http://www.bianceng.cn/Programming/cplus/

相关文章
  • 没有相关文章
  • 徐汉涛(www.xuhantao.com) © 2024 版权所有 All Rights Reserved.
  • 部分内容来自网络,如有侵权请联系站长尽快处理 站长QQ:965898558(广告及站内业务受理) 网站备案号:蒙ICP备15000590号-1