【问题标题】:Port forward app isn't working and I can't figure out why端口转发应用程序不起作用,我不知道为什么
【发布时间】:2013-01-18 11:54:34
【问题描述】:

我需要编写一个快速简便的端口转发器。目前它接受连接并且可以很好地从客户端读取,但是它没有从它运行的本地机器上得到任何东西。 (仅供参考,这是为了转发网络服务器,因为我找不到我通常用来将 VS2010/2012 转发到网络的应用程序,所以我自己做了)。

我知道异常吞咽,这很糟糕,但现在这并不重要,我可以稍后处理。

import java.io.*;
import java.net.*;

public class SocketForward {
  int src = 0;
  int dest = 0;
  public static void main(String args[]) throws Exception {
    if (args.length < 2) {
      System.out.println("Usage: java SocketForward <source port> <destination port>");
      System.exit(1);
    } else {
      new SocketForward().startRun(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
    }
  }
  public void startRun(int src, int dest) throws Exception {
    try {
      this.src = src;
      this.dest = dest;
    } catch (NumberFormatException e) {
      System.out.println("Usage: java SocketForward <source port> <destination port>");
      System.exit(1);
    }
    ServerSocket server = new ServerSocket(dest);
    System.out.println("Waiting for connections...");
    while (!server.isClosed()) {
      new ConnHandler(src, server.accept());
    }
  }
}

class ConnHandler implements Runnable {
  Socket clientSocket;
  Socket hostSocket;
  int hostport;
  Thread thread;
  BufferedOutputStream hostOut;
  BufferedOutputStream clientOut;
  BufferedInputStream hostIn;
  BufferedInputStream clientIn;
  public ConnHandler(int hostport, Socket clientSocket) {
    System.out.println("Connected to " + clientSocket.getInetAddress());
    this.clientSocket = clientSocket;
    this.hostport = hostport;
    this.thread = new Thread(this);
    thread.start();
  }
  @Override
  public void run() {
    try {
      hostSocket = new Socket("", hostport);
      System.out.println("Connected to localhost:" + hostport);
      hostOut = new BufferedOutputStream(hostSocket.getOutputStream());
      clientOut = new BufferedOutputStream(clientSocket.getOutputStream());
      hostIn = new BufferedInputStream(hostSocket.getInputStream());
      clientIn = new BufferedInputStream(clientSocket.getInputStream());
      new Thread() {
        public void run() {
          while (this == Thread.currentThread()) {
            byte[] buf = new byte[8192];
            try {
              int len = 0;
              while ((len = ConnHandler.this.clientIn.read(buf)) > 0) {
                System.out.println("Client: " + new String(buf, 0, len));
                ConnHandler.this.hostOut.write(buf, 0, len);
              }
            } catch (Exception e) {
              e.printStackTrace();
              break;
            }
          }
        }
      }.start();
      new Thread() {
        public void run() {
          while (this == Thread.currentThread()) {
            byte[] buf = new byte[8192];
            try {
              int len = 0;
              while ((len = ConnHandler.this.hostIn.read(buf)) > 0) {
                System.out.println("Host: " + new String(buf, 0, len));
                ConnHandler.this.clientOut.write(buf, 0, len);
              }
            } catch (Exception e) {
              e.printStackTrace();
              break;
            }
          }
        }
      }.start();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

【问题讨论】:

    标签: java networking io


    【解决方案1】:

    您没有进行任何刷新,从而引入了不透明的中间人行为。这很可能会扰乱客户端和服务器所期望的数据流。

    关于代码风格的附注:在while 循环之外有try-catch 更方便,所以它会自动爆发:

    try {
      while (...) ...
    } catch (Throwable t) {
       t.printStackTrace();
    }
    

    还要注意Throwable 而不是Exception——你会想知道任何会破坏你的代码的错误,而不仅仅是Exceptions。

    【讨论】:

    • 不敢相信我忘记了这么简单的事情。谢谢。我会尽快接受。
    • 我想说你的用例不能从缓冲流中受益,所以最好使用原始流。这并不意味着您必须逐字节阅读;原始流还支持读取/写入调用方提供的字节缓冲区。
    • 习惯 :) 我只是需要这个来进行测试,现在它已经达到了它的目的,可以放在我硬盘上安全的地方。
    • 关于Throwable,它也会捕获像OutOfMemoryError 这样的东西,我在代码中无能为力,真的。 Exception 足以捕获所有需要的已检查异常。
    • 好吧,你不能(也不要)对任何异常做任何事情,但你想知道它发生了,而不是让你的代码神秘地结束。跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 2021-10-26
    • 2016-11-11
    • 2016-08-25
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多