package j3; // いんちきHTTPサーバThttpd.java スレッド対応版 // このプログラムはポート番号8000番で動作するサーバです // 使い方: java j3.Thttpd ファイル名 ポート番号 // WWWクライアントからの接続に対して、引数で指定したファイルを返します。 // ライブラリの利用 import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.time.LocalDateTime; // Thttpdクラス public class Thttpd { public static void main(String args[]) { // サーバソケット ServerSocket servsock = null; Socket sock; // その他 if (args.length == 0) // 引数がない場合、以下のファイルを返すことにする args = new String[] { "src/j3/index.html" ,"8000"}; // 相対パスで指定。windowsの場合、user.dir=NWP // args = new String[] { "j3/index.html" };//Linuxの場合、通常はcd NWP/src しているはず System.out.println("このサーバは" + args[0] + "を返します。"); System.out.println(System.getProperty("user.dir")); int portnum = Integer.parseInt(args[1]); try { // サーバ用ソケットの作成(デフォルトでは、ポート番号8000番) servsock = new ServerSocket(portnum); while (true) { sock = servsock.accept();// 接続要求の受付 new RequestHandler(sock, args[0]); } } catch (IOException e) { System.out.println("異常終了:ポート番号("+portnum+")がすでに使われているようです"); System.exit(1); // 異常終了は1 } } } class RequestHandler implements Runnable { Socket sock; Thread thread; // 入出力 DataOutputStream dostr; BufferedReader in; FileInputStream infile = null; byte[] buff = new byte[1024]; String file; RequestHandler(Socket s, String file) { sock = s; this.file = file; thread = new Thread(this); thread.start(); } public void run() { try { process(); } catch (IOException e) { e.printStackTrace(); } thread = null; } void process() throws IOException { System.out.println("---\nConnection Requst from: " + (sock.getInetAddress())); // 読み書き用オブジェクトの生成 in = new BufferedReader(new InputStreamReader(sock.getInputStream())); dostr = new DataOutputStream(sock.getOutputStream()); // read headers StringBuffer request = new StringBuffer(); String line; String[] get = null; // GETリクエストをスペースで区切った配列 while ((line = in.readLine()) != null) { System.out.println(line); // 先頭がGETだったら if (line.toLowerCase().startsWith("get ")) { get = line.split(" "); // GET / HTTP/1.1 をスペースで区切った配列get を得る } request.append(line + "\r\n"); if (line.length() < 1) break; } String CRLF = "\r\n"; // Response Headerの出力 String response = "HTTP/1.1 200" + CRLF + "Content-type: text/html; charset=UTF-8" + CRLF + CRLF; // もし、リクエストがfaviconだったら if (get[1].endsWith(".ico")) { response = "HTTP/1.1 200" + CRLF + "Content-type: image/x-icon" + CRLF + CRLF; } else if (get[1].endsWith(".java")) { response = "HTTP/1.1 200" + CRLF + "Content-type: text/plain; charset=UTF-8" + CRLF + CRLF; } if (!get[1].equals("/")) { // リクエストファイルがあれば、/index.html の部分を書き換える file = file.replaceAll("/index.html", get[1]); } // オブジェクトinfileを作り,ファイルを準備します try { infile = new FileInputStream(file); } catch (Exception e) { // ファイル準備の失敗 System.err.println(file + " ファイルがありません"); response = "HTTP/1.1 404" + CRLF + CRLF; } dostr.write(response.getBytes()); // Response Bodyの出力 boolean cont = true; while (cont) { // ファイルからの読み込みとネットワーク出力 try { int n = infile.read(buff); dostr.write(buff, 0, n); } catch (Exception e) { // end of file cont = false; } } if (file.endsWith("index.html")) { // おまけ:レスポンスヘッダを表示 dostr.write(request.toString().getBytes()); // おまけ:時刻表示 dostr.write("</pre> \n\n <h2>Current DateTime (Thttpdが動的に生成した情報)</h2>".getBytes()); dostr.write(LocalDateTime.now().toString().getBytes()); } // 接続終了 sock.close(); infile.close(); } }