当前位置: 首页 > 面试题库 >

用Java快速实现端口转发

唐阳飇
2023-03-14
问题内容

我已经构建了一个打开ServerSocket的简单应用程序,并在连接时将其自身连接到远程计算机上的另一个服务器套接字。为了实现端口转发,我使用了两个线程,一个线程从本地输入流读取并向远程套接字输出流读取流,反之亦然。

该实现感觉有点差劲,所以我问您是否知道更好的实现策略,或者是否有一些代码可以以高效的方式实现。

PS:我知道我可以在Linux上使用IPTables,但是必须在Windows上才能使用。

PPS:如果您发布此简单任务的实现,我将创建一个基准测试所有给定的实现。对于许多小型(〜100bytes)封装和稳定的数据流,该解决方案应该是快速的。

我当前的实现是这样(在每个方向的两个线程中的每个线程上执行):

public static void route(InputStream inputStream, OutputStream outputStream) throws IOException {
    byte[] buffer = new byte[65536];
    while( true ) {
        // Read one byte to block
        int b = inputStream.read();
        if( b == - 1 ) {
            log.info("No data available anymore. Closing stream.");
            inputStream.close();
            outputStream.close();
            return;
        }
        buffer[0] = (byte)b;
        // Read remaining available bytes
        b = inputStream.read(buffer, 1, Math.min(inputStream.available(), 65535));
        if( b == - 1 ) {
            log.info("No data available anymore. Closing stream.");
            inputStream.close();
            outputStream.close();
            return;
        }
        outputStream.write(buffer, 0, b+1);
    }
}

问题答案:

一些观察:

  • 在循环开始时读取一个字节不会提高性能。实际上可能相反。

  • inputStream.available()不需要调用。您应该只尝试读取“缓冲区大小”字符。read套接字流上的A 将返回与当前可用字符一样多的字符,但是直到缓冲区已满时才会阻塞。(我无法在javadocs中找到任何说明这一点的方法,但是我敢肯定是这种情况。如果read阻塞直到缓冲区已满,很多事情都会表现不佳…或破坏…。)

  • 正如@ user479257指出的那样,您应该通过使用java.nio并读写ByteBuffer获得更好的吞吐量。这将减少在JVM中发生的数据复制量。

  • 如果读取,写入或关闭操作引发异常,则您的方法将泄漏Socket流。您应该使用try ... finally以下方法来确保无论发生什么情况始终关闭流。

public static void route(InputStream inputStream, OutputStream outputStream) 
throws IOException {
    byte[] buffer = new byte[65536];
    try {
        while( true ) {
            ...
            b = inputStream.read(...);
            if( b == - 1 ) {
                log.info("No data available anymore. Closing stream.");
                return;
            }
            outputStream.write(buffer, 0, b+1);
        }
    } finally {
        try { inputStream.close();} catch (IOException ex) { /* ignore */ }
        try { outputStream.close();} catch (IOException ex) { /* ignore */ }
    }
}


 类似资料:
  • 查看某个接口在哪里被实现 操作步骤: 菜单栏: Navigate —> Implementation 快捷键: Mac: Option + Command + B Windows\/Linux: Ctrl + Alt + B

  • 本文向大家介绍Mac中使用Nginx实现80端口转发8080端口,包括了Mac中使用Nginx实现80端口转发8080端口的使用技巧和注意事项,需要的朋友参考一下 由于项目本身的原因,开发必须使用80端口实现,而在Unix内核中非Root用户无法直接使用1024以下的端口,最初作者找到了pfctl的方式实现80端口转发到8080端口实现访问,经过亲测出现了最为严重的问题,按照当时的方法配置好之后发

  • 本文向大家介绍java实现快速排序算法,包括了java实现快速排序算法的使用技巧和注意事项,需要的朋友参考一下 1、算法概念。 快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。 2、算法思想。 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序

  • 本文向大家介绍利用virtualbox虚拟机实现端口转发,包括了利用virtualbox虚拟机实现端口转发的使用技巧和注意事项,需要的朋友参考一下 virtualbox虚拟机实现端口转发,具体内容如下 1.应用场景 突破上网限制(如在公司内部限制访问外部网络,但是开放了某些端口,可以利用开放的某些端口实现端口重定向) 远程桌面重定向 NC重定向获得Shell 2.实验环境 virtualbox虚拟

  • 本文向大家介绍SSH端口转发实现内网穿透的实现,包括了SSH端口转发实现内网穿透的实现的使用技巧和注意事项,需要的朋友参考一下 我们局域网的机器能够访问外网,但是外网不能访问内网。因为内网访问互联网时候能确定外网的地址,外网却不能确定我们局域网内的具体地址。(ip地址有限)如果 我们在访问外网的时候,这个链接让他保持、不断,那么这个链接就相当于我们建了一条路,内网数据能出去,外网数据能进来,ssh

  • 本文向大家介绍VIM实现文件快速跳转插件详解,包括了VIM实现文件快速跳转插件详解的使用技巧和注意事项,需要的朋友参考一下 前言 日常使用 VIM 的时候经常有跳转到特定目录下某个文件的需求: 使用 vimwiki 记笔记时会默认把所有笔记保存在目录 ~/vimwiki 下, 当我们想查看某个笔记时就打开那个目录下的某个文件; 我平时会写一些 shell 工具, 保存在 ~/bin 目录下, 就会