Source:
public void start() { try { serverSocket = new ServerSocket(localPort, 10, bindAddress); serverSocket.setSoTimeout(5000); } catch (IOException e) { throw new RuntimeException(e); } new Thread(() -> { while (latch.getCount() > 1) { try { Socket localSocket = serverSocket.accept(); Socket remoteSocket = new Socket(remoteAddress, remotePort); remoteSocket.setSoTimeout(20000); new Thread(() -> { try (InputStream remoteSocketInputStream = remoteSocket.getInputStream(); OutputStream localSocketOutputStream = localSocket.getOutputStream()) { log.debug("remote->local: opened"); byte[] remoteBuffer = new byte[4096]; int remoteBytesRead; while ((remoteBytesRead = remoteSocketInputStream.read(remoteBuffer)) != -1) { localSocketOutputStream.write(remoteBuffer, 0, remoteBytesRead); localSocketOutputStream.flush(); log.debugf("remote->local: transferred %d bytes\n", remoteBytesRead); } } catch (IOException e) { log.error("remote->local", e); } finally { } }).start(); try (InputStream localSocketInputStream = localSocket.getInputStream(); OutputStream remoteSocketOutputStream = remoteSocket.getOutputStream()) { log.debug("local->remote: opened"); byte[] localBuffer = new byte[4096]; int localBytesRead; while ((localBytesRead = localSocketInputStream.read(localBuffer)) != -1) { remoteSocketOutputStream.write(localBuffer, 0, localBytesRead); remoteSocketOutputStream.flush(); log.debugf("local->remote: transferred %d bytes\n", localBytesRead); } } catch (IOException e) { log.error("local->remote", e); } finally { Util.close(remoteSocket); } } catch (IOException e) { log.error("connect", e); } } latch.countDown(); }).start(); }

Target:
public void start() { try { serverSocket = new ServerSocket(localPort, 10, bindAddress); serverSocket.setSoTimeout(5000); } catch (IOException e) { throw new RuntimeException(e); } new Thread(() -> { while (latch.getCount() > 1) { try (Socket localSocket = serverSocket.accept(); Socket remoteSocket = new Socket(remoteAddress, remotePort);) { remoteSocket.setSoTimeout(20000); new Thread(() -> { try (InputStream remoteSocketInputStream = remoteSocket.getInputStream(); OutputStream localSocketOutputStream = localSocket.getOutputStream()) { log.debug("remote->local: opened"); byte[] remoteBuffer = new byte[4096]; int remoteBytesRead; while ((remoteBytesRead = remoteSocketInputStream.read(remoteBuffer)) != -1) { localSocketOutputStream.write(remoteBuffer, 0, remoteBytesRead); localSocketOutputStream.flush(); log.debugf("remote->local: transferred %d bytes\n", remoteBytesRead); } } catch (IOException e) { log.error("remote->local", e); } }).start(); try (InputStream localSocketInputStream = localSocket.getInputStream(); OutputStream remoteSocketOutputStream = remoteSocket.getOutputStream()) { log.debug("local->remote: opened"); byte[] localBuffer = new byte[4096]; int localBytesRead; while ((localBytesRead = localSocketInputStream.read(localBuffer)) != -1) { remoteSocketOutputStream.write(localBuffer, 0, localBytesRead); remoteSocketOutputStream.flush(); log.debugf("local->remote: transferred %d bytes\n", localBytesRead); } } catch (IOException e) { log.error("local->remote", e); } finally { Util.close(remoteSocket); } } catch (IOException e) { log.error("connect", e); } } latch.countDown(); }).start(); }