stupid_fishman 2023-06-05 17:53 采纳率: 25%
浏览 19

两台不同局域网的主机可以不通过公网服务器进行通讯吗?

如果我事先知道两台不同局域网的主机的映射IP地址和映射端口号,并且双方都通过某种网络通讯工具(socket)向对方发送数据,使双方的路由器建立映射表,那么可以不通过公网服务器进行通讯吗?

  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-06-05 20:11
    关注
    • 你可以看下这个问题的回答https://ask.csdn.net/questions/7769353
    • 除此之外, 这篇博客: 网络编程中的 (1). 创建 Socket:根据指定服务端的 IP 地址或端口号构造Socket类对象。若服务器端响应,则建立客户端到服务器的通信线路。若连接失败,会出现异常。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    • // 向服务器(域名是host。端口号为port)发起TCP连接,若成功,则创建Socket对象,否则抛出异常。
      Scocket socket = new Socket(InetAddress.getByName("LAPTOP-RSJSE505"),9999);
      // 根据InetAddress对象所表示的IP地址以及端口号port发起连接。
      Socket socket = new Socket(InetAddress.getByName("172.17.31.57"),9999);
      
    • 以下回答由chatgpt基于相关博客总结生成:

      对于两台不同局域网的主机,在没有公网服务器的情况下进行通讯并不是一件容易的事情。因为局域网和公网是隔离的,也就是说,两台主机之间是无法直接通讯的。但是,在一些特殊情况下,可以通过使用NAT(网络地址转换)来实现两台主机之间的通讯。

      具体实现方法如下:

      1. 在两台主机上都安装一个支持UPnP协议的软件,如端口映射工具。

      2. 在局域网中,通过UPnP协议向路由器申请外网IP和端口的映射。

      3. 通过UPnP协议向路由器注册一个回调监听函数,以便在路由器映射规则发生变化时能够及时得到通知。

      4. 在程序中设置一个监听端口并绑定到本地IP地址。

      5. 创建一个套接字并连接远程主机的映射IP地址和端口号。

      6. 发送数据。

      7. 接收数据。

      参考代码如下:

      import java.net.*;
      import java.io.*;
      
      public class Client {
      
         public static void main(String [] args) {
            String serverName = "192.168.1.100";
            int port = 9999;
            try {
               // 创建一个套接字并连接远程主机的映射IP地址和端口号
               Socket client = new Socket(serverName, port);
               System.out.println("已连接到主机: " + client.getRemoteSocketAddress());
               // 发送数据
               OutputStream outToServer = client.getOutputStream();
               DataOutputStream out = new DataOutputStream(outToServer);
               out.writeUTF("Hello from " + client.getLocalSocketAddress());
               // 接收数据
               InputStream inFromServer = client.getInputStream();
               DataInputStream in = new DataInputStream(inFromServer);
               System.out.println("服务器响应: " + in.readUTF());
               // 关闭套接字
               client.close();
            } catch (IOException e) {
               e.printStackTrace();
            }
         }
      }
      
      import java.net.*;
      import java.io.*;
      
      public class Server extends Thread {
         private ServerSocket serverSocket;
      
         public Server(int port) throws IOException {
            // 在程序中设置一个监听端口并绑定到本地IP地址
            serverSocket = new ServerSocket(port);
            serverSocket.setSoTimeout(100000);
         }
      
         public void run() {
            while(true) {
               try {
                  System.out.println("等待远程连接,端口号为:" + serverSocket.getLocalPort() + "...");
                  // 等待客户端连接
                  Socket server = serverSocket.accept();
                  System.out.println("远程主机地址:" + server.getRemoteSocketAddress());
                  // 接收数据
                  DataInputStream in = new DataInputStream(server.getInputStream());
                  System.out.println(in.readUTF());
                  // 向客户端发送响应数据
                  DataOutputStream out = new DataOutputStream(server.getOutputStream());
                  out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!");
                  // 关闭套接字
                  server.close();
               } catch (SocketTimeoutException s) {
                  System.out.println("Socket timed out!");
                  break;
               } catch (IOException e) {
                  e.printStackTrace();
                  break;
               }
            }
         }
      
         public static void main(String [] args) {
            int port = 9999;
            try {
               // 开启服务器监听
               Thread t = new Server(port);
               t.start();
            } catch (IOException e) {
               e.printStackTrace();
            }
         }
      }
      

      需要特别注意,因为NAT的运作机制是根据TCP/UDP数据包的头字段进行操作,所以使用非标准的TCP/UDP数据包(例如自定义TCP/UDP数据包)可能会导致NAT无法工作。此外,由于UPnP协议实现较为复杂,在使用过程中也要注意网络安全问题。

    评论

报告相同问题?

问题事件

  • 修改了问题 6月5日
  • 创建了问题 6月5日