欢迎使用CSDN-markdown编辑器

python实现内网穿透,用自己主机搭建服务器

参考:http://www.cnblogs.com/chulung/p/5657073.html


需求发起

  一直想用自己电脑搭建一个服务器,享受一下云服务带给人的快感。问题来了,小屌丝一枚,服务器主机可以用台式机凑合一下,但是没公网ip啊。服务器在内网,这个时候还是得用内网穿透。

  无法回避的问题,既然要穿透,服务器又在内网,必然借助第三方公网ip(别提花生壳了,及其不稳定,而且应该还没有linux客户端,受制于人的感觉,相当难受) 在淘宝店买了一个最低配的vps,用来当中转站(别问买了vps为什么不直接来用,便宜的坑爹货,配置太低,tomcat要启动3分钟。。。)。好了,开始!

中转站运行环境:

  • linux环境任意
  • jdk版本1.7,至少要高于这个版本才能跑python3.5
  • 听说python要快点,那就先搞定python环境了。python版本3.5.2
     (开发工具用的pycharm,这个随意就好)

设计思路:

  中转站实现方式:中转站用多线程服务器模型(中转站本质也是一个服务器)。接收来自的客户端或者服务器请求。

1.当服务器连接时,保存服务器的信息(包括ip和端口),然后就这样了,tcp长连接,不断开
2.当客户端连接时,中转站直接将消息转发给服务器,因为中转站已经在第1步和服务端保持了连接,直接用和服务通信的socket,就可以send过去了
3.当服务器接收到消息时,服务器处理后,然后同一个socket发送给中转站,中转站收到消息后,原封不动的转给客户端。
以上,2和3 就完成了一次客户端 –>中转站–>服务器–>中转站–>客户端的完整请求和答复。
思路是非常简单的,python代码实现也相当的简单:

(以下代码用了一些简单的自定义协议,所以,代码仅供参考)

代码实现

import socketserver
import  threading

SOCK_MAP_ADDRESS={}

class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass

class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):

    def handle(self):
        while True:
            data = str(self.request.recv(1024), 'utf_8')
            cur_thread = threading.current_thread()
            print(self.client_address,data)
            if (data == "server_login"):#服务器注册自己的信息
                global  SOCK_MAP_ADDRESS
                SOCK_MAP_ADDRESS["server"] = self.request #将服务器已建立连接sock插入字典
                self.request.send(bytes("login true","utf_8"))
            else :
                str_array = data.split("+")
                if (str_array[0] == "to_client"): #如果是来自服务器的消息
                    key = "{}+{}".format(str_array[1],str_array[2]) #根据key取客户端的sock和地址
                    sock = SOCK_MAP_ADDRESS[key]
                    sock.send(bytes(str_array[3],"utf_8")) #将消息发送到客户端
                else :   #来自客户端的消息
                    key = "{}+{}".format(self.client_address[0],self.client_address[1])
                    SOCK_MAP_ADDRESS[key] = self.request #将客户端已经建立连接的sock插入字典
                    sock = SOCK_MAP_ADDRESS["server"] #获取服务器的sock
                    to_server_data = "to_server+{}+{}".format(key, data)
                    sock.send(bytes(to_server_data,"utf_8"))

if __name__ == "__main__":
    HOST, PORT = "103.*.*.*", 9999
    server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
    ip, port = server.server_address
    server_thread = threading.Thread(target=server.serve_forever)
    # Exit the server thread when the main thread terminates
    server_thread.daemon = True
    server_thread.start()
    server_thread.join()import socketserver

以上,就是可以实现内网穿透功能。

设计改进:

1,中转站和服务器不必常连接,当服务器第一次连接中转站的时候,中转站就知道了服务器的位置,然后如果中转站连接服务器,直接新建一个套接字连接即可。所以,如果服务器是tomcat,中转站就可以通过ip和tomcat监听的端口,将数据发过去,这样子tomcat就能响应这个请求。(tomcat无法实现主动连接中转站,所以,第一次告诉中转站的位置信息,可以自己写一个python脚本,20行不到。。。)
2,可以基于udp通信,然后让中转站告诉服务器和客户端对方的位置,让服务器和客户端通过udp直接通信,因为udp不需要保持连接状态。代码暂未实现,当然这个也有限制,上面那种方法是一定可以的,缺点就是受制于三方网络。
3,现在百度云有个云引擎,很便宜,可以将中转站部署在上面,这样子就可以用很少的成本,完成内网穿透。(具体实现是个坑,三思而后行。。。。)

你可能感兴趣的:(python,服务器,云服务)