吵吵   2015-09-06  阅读:793

本文讲的是关于文件传输的内外网打通的相关技术问题,不感冒请去吹风。

回到我前面做的实验室的QQ的问题上,文件传输,用socket直接把文件发送过去,这是不用说的。但是如果我们的客户端有些在内网,有些在外网呢,如果中间还有路由器,还需要做NAT呢?


一、飞鸽是怎么做的?

内网文件的传输飞鸽是大大有名的,飞鸽的机制是什么样的呢?A客户端向B客户端发送文件传输的请求,B确定接收后,A直接将文件向B发送。实际上来说,飞鸽是没有服务端的,所有的通讯它都是Point to Point,也不需要服务端来进行调度。但是这会引发个问题,就是如果客户端A、B是通过了路由器的,那么它们的出口IP都是相同的,如果信息从C返回来的时候,路由器就没有办法把端口映射到A还是B,这个数据包就没有办法到达A或者是B。

二、文件传输NAT的解决办法。

鉴于以上的原因,于是我设计的实验室QQ就增加了一个服务端,这个时候,如果两个都是路由器里面的A、B连接到了服务端,那么服务端给A、B以及路由器之外的C都分配一个UID,C给A发送的数据,经服务端判断该数据包的流向是A,然后调用A的socket,将数据包写入,那么A就收到了C发给它的数据。

为了提高服务器的转发效率,我做了一些改动:

1、服务器的客户端socket列表采用Dictionary,并将UID设为该列表的key,因此一旦我们得到了UID,就可以快速找到相应的socket。

2、在数据包结构中增加了FromUID和ToUID的包头,服务端在未解析该包之前判断是否进行转发,如果只是转发则获取ToUID,找到相应的Socket进行转发。

三、内外网问题的解决办法。

我办公室的电脑有些是内网的,有些是外网的,从外网下载一个东西,放到内网来,就需要用U盘进行转发,这是个相当麻烦的事情。为了打通内外网之间的传输,我把服务端程序放到一台双网卡的服务器上,则外网使用外网的ip地址连接,内网使用内网的ip地址连接,由于服务端的转发作用,则内外网就通了。

四、转发真的有足够的效率么?

一开始,文件读取和发送我用了一个单独的线程来完成,为了控制发送的速度,我用Thread.sleep(100)来延缓一下发送的速度,于是乎一个100k的文件传了半天!将中间休眠的时间改小Thread.sleep(1),速度是变快了,最多是500k/s,但是内网的速度至少应该是10M/s啊,这个差别大了!

莫非服务端的转发效率真的很低,传统的文件发送方式是直接点对点的,但是通过服务端的转发,等于是中间多了一次socket的读取,又多了一次socket的写入,所以速度会这么慢?但是反过来想,即便是中间多出来的操作占用了多了一半的时间,那么传输速度也至少有5M/s啊,为什么还是相差10倍?读取和写入都是内存操作,应该不至于会造成那么多的延迟啊!

我只得先跟踪服务端接收数据包的速度,发现没有问题,在跟踪它转发数据包的速度,还是没有问题!

最后把Thread.sleep(1)给去掉了,世界终于安静了,文件传输的速度直接飙到10M/s了!原来休眠1ms,与不休眠的差别会这么大!!

同时也证明,其实通过服务端的转发,也损失不了多少性能,但是前提是的客户端足够少,若是像腾讯的那种,估计早就死翘翘了。

吵吵微信朋友圈,请付款实名加入:

吵吵 吵吵

发表评论

电子邮件地址不会被公开。 必填项已用*标注