利用内网穿透实现Socket外网通信

1. 前言

需求提出:还有两三天就要参加毕业设计答辩了。一直在考虑怎么样给老师做展示才好。由于毕设做的是基于深度学习的去雾研究。只有一台PC,也就意味着只能录屏?感觉录屏不好啊,所以想了下要不做个Android App展示去雾?可是研究了下把Keras模型移植到Android上似乎也不太轻松,因为我的模型中有些自定义层,不是标准的模型。再来就想要不把模型放到服务器上?但是我的服务器性能这么垃圾,而且服务器在国外,上传下载速度也不行。最后,要不就拿现在这台PC来做?可是问题来了,我怎么才能走广域网连接PC呢,毕竟答辩不可能在寝室。
OK,百度一波,还是选择内网穿透吧。

第一次接触内网穿透是在去年10月还是11月的“搭建aria2远程下载机”。所以对内网穿透这个名词还不算陌生。(看样子曾经无聊搞的东西还是可能在未来帮到自己啊)

好了,废话了一堆,本文要做的功能有:

  1. 以台式机作为服务器,等待客户端上传图片,服务器将图片去雾后回传给客户端。
  2. 既然台式机要做服务器,那就必须来个内网穿透了,不然外网的手机是不能连接到PC的。
  3. 服务器与客户端的通信使用的Socket

2. 正文“斯达头”(start)

2.1 材料准备

  1. PC机
  2. 花生壳账号

2.2 花生壳注册与端口映射

登陆官网,并注册:https://hsk.oray.com/

然后进入控制台。进入域名注册:

自己注册一个域名吧,用不了多少钱。

然后打开内网穿透,新增映射。

填写你的相关信息。

这里再说一下如何查IP。

方法一:如果使用了路由器,可以打开路由器查:

方法二:直连网线或wifi的,在cmd窗口用ipconfig命令查看。

注意你的连接方式,我是有线所以找的以太网适配器。如果是无线,记得找无线适配器的地址。

最后下载花生壳的内网穿透客户端到PC上,记得下载3.0版本,5.0 beta版经测试还是有bug。

花生壳3.0 版本:https://hsk.oray.com/download/download?id=hskddns_310

下载好后,安装并登陆打开。

2.3 测试是否映射成功

打开在线端口映射工具:http://tool.chinaz.com/port/

记住外网的域名和端口,依此填入即可。

显示“开启”字样,则表示穿透成功。

3. 测试Socket通信

在我的测试中,python作为Socket服务端,Android作为Socket客户端。对应代码如下

3.1 Socket服务端

def socket_service():
    """
    开启socket服务
    :return:
    """
    # 开启socket服务
    try:
        s = socket.socket()
        s.bind(('192.168.1.104', 6666))
        s.listen(10)
    except socket.error as msg:
        print(msg)
        sys.exit(1)

    print("Wait")

    def save_haze_file(sock):
        """
        从sock中获取数据,并保存下来
        :param sock:
        :return:
        """
        with open(haze_path, 'wb') as f:
            print('file opened')
            while True:
                data = sock.recv(1024)
                # print()
                if not data:
                    break
                elif 'EOF' in str(data):
                    f.write(data[:-len('EFO')])
                    break
                # write data to a file
                f.write(data)
        # sock.close()
        print('pic received finished')

    def send_img(sock):
        # 发送处理后的图片
        with open(dehaze_path, 'rb') as f:
            for data in f:
                sock.send(data)
        print('send finished')

    # 等待连接并处理
    idx = 0
    while True:
        sock, _ = s.accept()
        # idx += 1
        # if idx == 1:
        #     save_haze_file(sock)
        # elif idx == 2:
        #     idx = 0
        try:
            save_haze_file(sock)
            dehaze()
            send_img(sock)
        except Exception as reason:
            print(reason)
        finally:
            sock.close()

上述代码,就是建立Socket服务端,服务端的IP为内网IP。

3.2 Socket客户端

 private final String IP = "xxx";        // 这个地方的IP为内网穿透时给的ip
private final int PORT= xxx;                    // 同理为给的端口

private void sendImg(String path) throws IOException {
    // 创建一个Socket对象,并指定服务端的IP及端口号
    socket = new Socket(IP, PORT);
    InputStream inputStream = new FileInputStream(path);
    // 获取Socket的OutputStream对象用于发送数据。
    OutputStream outputStream = socket.getOutputStream();
    // 创建一个byte类型的buffer字节数组,用于存放读取的本地文件
    byte buffer[] = new byte[10 * 1024];
    int temp = 0;
    // 循环读取文件
    while ((temp = inputStream.read(buffer)) != -1) {
        // 把数据写入到OuputStream对象中
        outputStream.write(buffer, 0, temp);
        // 发送读取的数据到服务端
        outputStream.flush();
    }
    socket.close();
}

注意要修改的地址为IP和PORT。

查看方式如下:

红框表明的即为需要修改的IP,端口为“映射”字段后写的端口。

4. 结语

至此,已经实现了内网穿透并且通过Socket通信了。其余应用功能只用映射为其它端口即可。

本文涉及的所有代码已放于GIthub:https://github.com/ravenxrz/DeBlurGanToDehaze

Last modification:August 27th, 2019 at 10:44 am
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment