Home > Tags > Socket

Socket

シンプルな HTTP Server 書いた

以前の記事の続きということで、シンプルな HTTP Server を書いた。

classファイル一つで動くというお手軽サーバー。マルチスレッド?自分しか使わないからいいんですよ。
お手軽に使いたいのでデフォルトパッケージ。

java SimpleHttpServer "C:\htdocs" 81
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class SimpleHttpServer {

    private static String requestPath;

    private static Map<String, String> CONTENT_TYPES = new HashMap<String, String>();

    static {
        CONTENT_TYPES.put("html", "text/html");
        CONTENT_TYPES.put("htm", "text/html");
        CONTENT_TYPES.put("css", "text/css");
        CONTENT_TYPES.put("js", "text/javascript");
        CONTENT_TYPES.put("jpg", "image/jpeg");
        CONTENT_TYPES.put("jpeg", "image/jpeg");
        CONTENT_TYPES.put("png", "image/png");
        CONTENT_TYPES.put("gif", "image/gif");
        CONTENT_TYPES.put("pdf", "application/pdf");
        CONTENT_TYPES.put("txt", "text/plain");
        CONTENT_TYPES.put("xml", "text/xml");
        CONTENT_TYPES.put("zip", "application/zip");
        CONTENT_TYPES.put("exe", "application/octet-stream");
    }

    public static void main(String[] args) throws IOException {
        String documentRoot = args[0];
        int port = Integer.parseInt(args[1]);

        ServerSocket server = new ServerSocket(port);

        while (true) {
            Socket client = server.accept();

            // HTTPリクエストを出力
            outputRequest(client);

            // HTTPレスポンスを出力
            outputResponse(client, documentRoot);
        }
    }

    private static void outputRequest(Socket client) throws IOException {
        System.out.println("------------------------------------------");

        BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));

        // 1行目からリクエストパスを取得しておく(/でアクセスされた場合はindex.htmlを表示)
        String inline = br.readLine();
        requestPath = inline.split(" ")[1];
        if (requestPath.endsWith("/")) {
            requestPath += "index.html";
        }

        while (br.ready() && inline != null) {
            System.out.println(inline);
            inline = br.readLine();
        }

        System.out.println("------------------------------------------");
    }

    private static void outputResponse(Socket client, String documentRoot) throws IOException {
        PrintStream ps = new PrintStream(client.getOutputStream());

        String responseFile = documentRoot + requestPath;
        File file = new File(responseFile);

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);

            // ヘッダー出力
            int bodyLength = (int) file.length();
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Length: " + bodyLength);
            ps.println("Content-Type: " + getContentType(file));
            ps.println("");

            // ボディ出力
            byte buf[] = new byte[bodyLength];

            fis.read(buf);
            ps.write(buf, 0, bodyLength);
            ps.flush();
        } catch (FileNotFoundException e) {
            // ヘッダー出力
            ps.println("HTTP/1.1 404 Not Found");
            ps.println("");
            ps.println("<h1>指定されたファイルは存在しません。</h1>");
        } finally {
            if (fis != null) {
                fis.close();
            }
        }

        ps.close();
    }

    private static String getContentType(File file) {
        String extension = getExtension(file);

        String contentType = CONTENT_TYPES.get(extension);

        if (contentType == null) {
            return "text/html";
        } else {
            return contentType;
        }
    }

    private static String getExtension(File file) {
        String path = file.getPath();
        int lastDotPosition = path.lastIndexOf(".");

        String extension = null;
        if (lastDotPosition == -1) {
            extension = "";
        } else {
            extension = path.substring(lastDotPosition + 1).toLowerCase();
        }

        return extension;
    }
}

コードはGistにもペタリ。
https://gist.github.com/2260004

Socket の勉強のためにエコーサーバー書いた

前々から、Jarひとつで動くHTTPサーバーを書いてみたいと思っていて(既にたくさんあると思うけど)、それには Socket でがちゃがちゃしないといけないとの事だったので、重い腰を上げて Socket の勉強をしてみた。

とりあえず、リクエストされた文字列をそのまま返すだけのエコーサーバーを書いてみた。
一応、マルチスレッド対応。

Server

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class EchoServer {

    public static void main(String[] args) throws IOException {

        ServerSocket server = new ServerSocket(5000);

        // クライアントからの接続を待ち受ける
        while (true) {
            Socket client = server.accept();

            new Thread(new EchoServer().new EchoThread(client)).start();
        }
    }

    class EchoThread implements Runnable {

        Socket client;

        public EchoThread(Socket client) {
            this.client = client;
        }

        @Override
        public void run() {
            echo(client);
        }

        private void echo(Socket client) {
            System.out.println("処理開始");

            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
            }

            System.out.println("接続中 : " + client.getRemoteSocketAddress());

            try {
                InputStream in = client.getInputStream();
                OutputStream out = client.getOutputStream();

                int recvByte;
                while ((recvByte = in.read()) != -1) {
                    out.write(recvByte);
                }
            } catch (IOException e) {
                System.err.println(e);
            } finally {
                closeQuietly(client);
            }

            System.out.println("処理終了");
        }

        private void closeQuietly(Socket socket) {
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                // ignore
            }
        }
    }
}

Client

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class EchoClient {

    public static void main(String[] args) throws IOException {

        Socket socket = new Socket("localhost", 5000);
        System.out.println("サーバとの接続を確立 : " + socket.getLocalPort());

        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();

        byte[] data = args[0].getBytes();
        out.write(data);
        System.out.println("送信 : " + new String(data));

        int i = 0;
        byte[] output = new byte[data.length];
        int recvByte;
        while ((recvByte = in.read()) != -1) {
            output[i++] = (byte) recvByte;

            if (i >= data.length) {
                break;
            }
        }

        System.out.println("受信 : " + new String(output));

        socket.close();
    }
}

バイトの読み書きを1バイトずつやってるので、あまり効率的ではないんだろうな。

Home > Tags > Socket

Search
Feeds
Meta

Return to page top