这篇文章拖了5个月,生成的时间戳本来是2月7日的,现在是7月了。..其实它本来就是一个很简单的C/S模型。机器人HTTPServer是机器人局域网中的客户端(Web、桌面、Android/iOS)。客户端连接到机器的局域网,然后通过局域网的IP地址访问机器人上的HTTPServer来控制机器人。但是后面有个需求,当机器人插上3/4G网卡的时候,必须复用机器人上的HTTPServer来远程控制和访问机器人。那么问题来了,如何访问NAT后的HTTPServer呢?我研究了几种解决方案。使用SSH回显隧道将本地HTTPServer端口映射到公网服务器。但是也有很多缺点。一个机器人ServerPort对应一个公网ServerPort。机器人上会有很多不同后端工程师写的HTTPServerPorts,有几百台机器。映射关系的个数为HTTPServerPort*robots个数。机器人和服务数量庞大,管理非常操蛋。用于直接P2P通信的NAT打孔。其实这里面的内容很多,涉及4种NAT、UDP/TCP打洞,以及对应的两个协议STUN/TURN。它在跨网络地址转换器的对等通信一文中有详细描述。这里我就不细说了,但是目前的机型还没有这种方法。因为对于SymmetricNAT,不能保证Client的每个Request都会有相同的Port。使用Socket.io作为长链接转发。这是目前使用的方法,但是调用的方法有点难看。我们实际上使用了JSONRPC方法调用。首先在Socket.ioServer上定义JSON数据的事件转发给机器人,然后在机器人上定义事件接受转发,然后使用这些HTTPMetaJSONRPC访问本地服务器的HTTPServer,以及最后将定义好的JSONRPC传递回客户端。这个过程维护了两个Socket.io长连接,定义了很多转发事件,基本上就是一个基于Socket.io的JSONRPC。不过最近看了一个实践http://lifeofzjs.com/blog/2014/11/17/visit-server-behind-nat/。这种模式比JSONRPC更简单、更舒适。直接使用一个服务器的HTTPServer将Socket.io的JSONRPC转发给机器人,机器人返回的Response作为本服务器的HTTPServerResponse直接返回给Client。这样只维护一个Socket.io长连接,省去了JSONRPC的定义过程,并且通过公网的路由,/robots/:id可以对应访问不同的机器人。简单舒适。
