【C++】内外网连接原理与ASIO 代理

参考资料:《Boost Asio C++网络编程》第五章

学会网络编程之后,理所当然会有这样的想法:在单位电脑上部署自己写的服务段软件,在家里电脑上部署客户端,从而远程办公。但是实际操作下来可以发现,两台电脑上的ip地址,根本不能建立socket直连,这是为什么呢。

内外网连接规则

对于普通网络用户,电脑入网都分配的是内网IP。尽管IPv6已经出来多年,目前互联网公网IP普遍还在IPv4阶段,可利用的IP地址相当有限。宽带商本身仅仅能拿到少量IPv4地址的使用权,不会给每个个人用户配置单独的公网IP,为了让每个用户上网,把用户都纳入局域网中分配局域网IP;建立网关设备作为门户,收集每个用户的socket请求然后变为门户IP的数据包,转发到公网上去,建立长期连接;用户连接单独开启一个端口用于标识数据转发地址;但是不允许外网主动申请连接,如图1
【C++】内外网连接原理与ASIO 代理_第1张图片

图1
实际上,用户每次登录上网的IP都是动态的;而且转发数据包所用的端口也是动态的,所以外网根本没法主动定位内网电脑的地址,显然,单位和家里处于不同内网的两台电脑,也无法直接连接,全被网关服务器挡住了。
内网穿透

既然内网之间无法连接,内网的网络用户,需要其他方式才能进行互联,实现聊天、传文件、远程控制等功能。上述可知,内网能主动连接公网服务器建立长期连接,但不能反向,那么不同内网用户可以预先向同一公网服务器建立长期连接,然后公网服务器进行转发,间接实现内网电脑之间的互联,如图2:
【C++】内外网连接原理与ASIO 代理_第2张图片

图2
资源利用策略

一般情况下,一台公网服务器就会占用一个公网IP,如果服务量巨大,那这台服务器会崩溃,需要将压力分散到多个服务器中,一种可用策略如图3:
【C++】内外网连接原理与ASIO 代理_第3张图片

图3
这里,公网服务器在查看它的内网服务器的负载之后,决定将用户连接服务交给其中一台服务器进行处理,这些数据包同样经过了内网转发环节。不过这里还不清楚的是:如果一个IP配备一台网关服务器,巨大数据流量下,服务器得有多强的数据吞吐量? 实际服务中,为了有效利用网络资源,存在至少两种处理策略: 1. 一套服务器,统一管理所有的用户连接。该策略管理能力很强,常见的用法就是编写一个控制页面,随时封杀用户。这种策略在很多用户连接的情况下,压力成倍增长。 2. 分散的若干服务器,每台服务器管理一批用户进行小范围互联。P2P属于这种类型,对每个服务器的压力较小,可以轻松扩展,但是管理混乱。
ASIO代理服务

代理服务器很简单,需要配备两个端口,一个接收客户端sock连接,一个接收服务端socket连接。端口可以设置reuse属性,进行多进程监听,但是最好一个端口仅对应一个服务。

class proxy : public boost::enable_shared_from_this<proxy> {
proxy(ip::tcp::endpoint ep_client, ip::tcp::endpoint ep_serv
er) : ... {}
void on_start() {
	do_read(client_, buff_client_);
	do_read(server_, buff_server_);
}

这里是异步调用,直接启动client和server的监听即可,后续回调函数需要将sock作为参数,好识别究竟是客户端还是服务端发出了响应:

void do_read(ip::tcp::socket & sock, char* buff) {
	async_read(sock, buffer(buff, max_msg), MEM_FN3(read_com
plete,ref(sock),_1,_2), MEM_FN3(on_read,ref(sock),_1,_2));
}

注意这里使用std/boost::ref(),显示调用std/boost::bind执行引用参数传递,因为bind默认参数列表都是值传递。

void on_read(ip::tcp::socket & sock, const error_code& err,
size_t bytes) {
char * buff = &sock == &client_ ? buff_client_ : buff_se
rver_;
do_write(&sock == &client_ ? server_ : client_, buff, by
tes);
}

实际操作很简单,如果是client的sock读取进来,那么就向server的sock写入同样的数据;反之亦然。代理的一大作用在这里,就是可以把client/server传入的数据进行修改,再用不同的sock传递出去。

你可能感兴趣的:(C++)