前回のSocketを中継するプログラムをJavaで書き直してみた。C言語と比べるとだいぶすっきりしているがやっている事は同じである。
ソースコード
import java.net.*; import java.io.*; class SocketRelay implements Runnable { private Socket clientSocket; private Socket serverSocket; private class Relay implements Runnable { private InputStream inputstream; private OutputStream outputstream; private final int BUFFERSIZE = 1024 * 16; private byte buffer[] = new byte[BUFFERSIZE]; public Relay(InputStream inputstream, OutputStream outputstream) { this.inputstream = inputstream; this.outputstream = outputstream; } public void run() { try { while (true) { int ret = this.inputstream.read(buffer); if (ret == -1) { break; } synchronized (outputstream) { System.out.write(buffer, 0, ret); } this.outputstream.write(buffer, 0, ret); } } catch (Exception e) { e.printStackTrace(); } } } public SocketRelay(Socket clients, Socket servers) { this.serverSocket = servers; this.clientSocket = clients; } public void run() { try { InputStream clientInput = this.clientSocket.getInputStream(); OutputStream clientOutput = this.clientSocket.getOutputStream(); InputStream serverInput = this.serverSocket.getInputStream(); OutputStream serverOutput = this.serverSocket.getOutputStream(); Relay pushRelay = new Relay(serverInput, clientOutput); Relay pullRelay = new Relay(clientInput, serverOutput); Thread pushThread = new Thread(pushRelay); Thread pullThread = new Thread(pullRelay); pushThread.start(); pullThread.start(); pullThread.join(); pushThread.stop(); serverInput.close(); serverOutput.close(); clientInput.close(); clientOutput.close(); this.serverSocket.close(); this.clientSocket.close(); } catch (Exception e) { } } public static void main(String args[]) throws IOException { ServerSocket serverSocket=null; Socket connectedSocket, clientSocket; int inport, outport; try { inport = new Integer(args[1]).intValue(); outport = new Integer(args[2]).intValue(); serverSocket = new ServerSocket(inport); while (true) { connectedSocket = serverSocket.accept(); clientSocket = new Socket(args[0], outport); SocketRelay sr = new SocketRelay(clientSocket, connectedSocket); new Thread(sr).start(); } } catch (Exception e) { e.printStackTrace(); } } }
Javaは言語自体にネットワーク等のライブラリが充実しておりプラットフォームの違いを意識する事が無いので便利。C言語だと大抵のプラットフォームで動作するがANCI規格ではないコードは互換性がないので修正が必要になる。
使い方
$javac SocketRelay.java
$java SocketRelay localhost 8080 80
ブラウザ等でhttp://localhost:8080/へアクセス
ctrl+cで終了
出力例
GET / HTTP/1.1 Host: localhost:8080 Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31 Accept-Encoding: gzip,deflate,sdch Accept-Language: ja,en-US;q=0.8,en;q=0.6 Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.3 HTTP/1.1 200 OK Date: Tue, 16 Apr 2013 14:59:19 GMT Server: Apache/2.2.22 (Unix) DAV/2 PHP/5.3.15 with Suhosin-Patch mod_ssl/2.2.22 OpenSSL/0.9.8r Content-Location: index.html.en Vary: negotiate TCN: choice Last-Modified: Mon, 11 Feb 2013 08:55:12 GMT ETag: "35d48-2c-4d56f111c5c00" Accept-Ranges: bytes Content-Length: 44 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html Content-Language: en <html><body><h1>It works!</h1></body></html>GET /favicon.ico HTTP/1.1 Host: localhost:8080 Connection: keep-alive Accept: */* User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31 Accept-Encoding: gzip,deflate,sdch Accept-Language: ja,en-US;q=0.8,en;q=0.6 Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.3 HTTP/1.1 404 Not Found Date: Tue, 16 Apr 2013 14:59:20 GMT Server: Apache/2.2.22 (Unix) DAV/2 PHP/5.3.15 with Suhosin-Patch mod_ssl/2.2.22 OpenSSL/0.9.8r Content-Length: 209 Keep-Alive: timeout=5, max=99 Connection: Keep-Alive Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>404 Not Found</title> </head><body> <h1>Not Found</h1> <p>The requested URL /favicon.ico was not found on this server.</p> </body></html> ^C