我无法使用外部 ip 与 Java.Socket 连接我的电脑



我使用Java.Sockets制作了一个简单的套接字应用程序。我在同一台电脑上运行客户端和服务器,这台电脑与其他电脑连接了调制解调器。客户端可以连接到服务器与我的本地ip。但是当它尝试连接外部ip时,它失败了。

服务器代码:

    int portno=Integer.parseInt(args[0]);
    ServerSocket ssock = new ServerSocket(portno);

    while(true){
        Socket csock = ssock.accept();
        PrintWriter out = new PrintWriter(csock.getOutputStream(), true);
        BufferedReader in = new BufferedReader( new InputStreamReader(csock.getInputStream()));
        String buffer = in.readLine();
        System.out.println(buffer);
        csock.close();
    }

和客户端代码:

    public static void main(String args[]) throws Exception{
    String ip="My External IP";
    int port=Integer.parseInt(args[0]);
    Socket sock = new Socket(ip,port);
    PrintWriter out = new PrintWriter(sock.getOutputStream(), true);
    BufferedReader in = new BufferedReader( new InputStreamReader(sock.getInputStream()) );
    BufferedReader stdin =  new BufferedReader( new InputStreamReader(System.in) );
    String buffer=stdin.readLine();
    out.println(buffer);
    sock.close();
}

这就是socket变得复杂的地方。它们在封闭的网络上工作得很好,但是一旦它们被网络地址转换器(路由器)分开,你就需要寻找其他方法。

路由器阻止所有传入的流量/连接,除非路由器是专门端口转发的,或者传入的流量是对它自己的请求的回答(例如获取网页)

为了允许你的路由器接受连接,你需要配置它这样做。另一种方法是使用一种叫做"打孔"的方法。这是Skype等软件使用的一种技术。技术各不相同,而且大部分是非官方的,但其背后的一般概念是:

  • 计算机A想要访问计算机B
  • 计算机A和计算机B彼此不知道对方的位置,但都知道一个官方的超级节点。超级节点保存所有已连接用户的列表。
  • 一旦计算机A和计算机B从超级节点中检索到彼此的位置。
  • 计算机A向计算机B发送请求,在路由器上创建一个洞,等待响应。
  • 计算机B没有收到请求,它自己的路由器阻止了请求,但它知道计算机A想通过与超级节点通信来访问它。
  • 计算机B通过路由器的孔向计算机a发送一个新的数据包,使计算机a认为它收到了响应。计算机B现在有一个孔,连接反向,使其双向。现在两台电脑都已连接。

打孔是将客户端连接在一起的唯一方法之一,尽管它确实需要第三个"超级节点"。打孔是一种非官方的解决方案,不幸的是存在缺陷。并不是所有的路由器都支持打孔,这意味着没有具体的方法来连接客户端。还有另一种选择,使用STUN或ICE服务器。网上的文档很少,但我知道它可以作为连接两个客户机的中继。我自己也发了一个关于STUN服务器和客户端的问题。

在安全性和连接性之间有一个长期的斗争,在它被解决和p2p连接标准化之前,你将不得不寻找新的和创造性的方法来使它工作。

我希望这对你有帮助。

UDP打孔:http://en.wikipedia.org/wiki/UDP_hole_punching

眩晕:http://en.wikipedia.org/wiki/STUN

最新更新