欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

http - simple server & client

程序员文章站 2022-06-05 18:20:48
...

Simple http server & client implementation by pure j2se.

 

http - client:

package eric.j2se.net.http;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * <p>
 * A simple http client.
 * </p>
 * 
 * @author eric
 * @date Jan 6, 2014 4:29:54 PM
 */
public class SimpleHttpClient {
	/**
	 * send http request & get response,
	 * 
	 * @param host
	 *            hostname or ip
	 * @param path
	 *            path after host, format: "/xxx"
	 * @param port
	 * @return response string
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public static String httpRequest(String host, String path, int port) throws IOException, InterruptedException {
		Socket client = new Socket(host, port);
		StringBuffer requestInfo = new StringBuffer("");
		StringBuffer responseInfo = new StringBuffer("");

		// prepare request info,
		requestInfo.append("GET " + path + " HTTP/1.1\n");
		requestInfo.append("Host: " + host + "\n");
		requestInfo.append("Connection: Close\n");

		// send request,
		PrintWriter pw = new PrintWriter(client.getOutputStream(), true);
		pw.println(requestInfo.toString());
		System.out.println("****** request - start ******");
		System.out.println(requestInfo.toString());
		System.out.println("****** request - end ******");

		// get response info,
		LineNumberReader lnr = new LineNumberReader(new InputStreamReader(client.getInputStream()));
		String line;
		while ((line = lnr.readLine()) != null) {
			responseInfo.append(line + "\n");
		}
		System.out.println("****** response - start ******");
		System.out.println(responseInfo.toString());
		System.out.println("****** response - end ******");

		pw.close();
		lnr.close();
		client.close();
		return responseInfo.toString();
	}

	/****** test - start ******/
	/**
	 * test http request,
	 */
	public static void testHttpRequest() {
		try {
			httpRequest("localhost", "/index.html", 80);
			// sendRequest("www.google.com.hk", "/", 80);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {

	}
	/****** test - end ******/
}

 

 

http - server:

package eric.j2se.net.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

/**
 * <p>
 * A simple http server.
 * </p>
 * 
 * @author eric
 * @date Jan 9, 2014 10:10:48 PM
 */
public interface HttpServer {
	/**
	 * start server,
	 */
	void start();

	/**
	 * parse, get params,
	 * 
	 * @param is
	 * @return params
	 * @throws IOException
	 */
	Map<String, String> parse(InputStream is) throws IOException;

	/**
	 * read param from param string,
	 * 
	 * @param paramStr
	 *            params string, format: name1=value1&name2=value2\
	 * @param isBody
	 *            whether the params from body,
	 * 
	 * @return map of param key/value,
	 */
	Map<String, String> parseParam(String paramStr, boolean isBody);

	/**
	 * send response
	 * 
	 * @param os
	 * @param paramMap
	 */
	void response(OutputStream os, Map<String, String> paramMap);

	/**
	 * shutdown server,
	 * 
	 * @throws IOException
	 */
	void terminate() throws IOException;
}

 

package eric.j2se.net.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

/**
 * <p>
 * A simple http server implementation.
 * </p>
 * TODO ... add more feature
 * 
 * @author eric
 * @date Jan 10, 2014 2:53:50 AM
 */
public class SimpleHttpServer implements HttpServer {
	private ServerSocket server;

	public SimpleHttpServer(int port, int backlog, String host) throws UnknownHostException, IOException {
		server = new ServerSocket(port, backlog, InetAddress.getByName(host));
	}

	@Override
	public void start() {
		Socket socket = null;
		InputStream inStream = null;
		OutputStream outStream = null;

		Map<String, String> paramMap = null;

		while (true) {
			try {
				socket = server.accept();

				// get input
				inStream = socket.getInputStream();
				paramMap = parse(inStream);
				// paramMap = new HashMap();

				// write output
				outStream = socket.getOutputStream();
				response(outStream, paramMap);

				// close socket, this indicate the client that the response is finished,
				socket.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if (inStream != null) {
						inStream.close();
					}
					if (outStream != null) {
						outStream.close();
					}
					if (socket != null) {
						socket.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@Override
	public Map<String, String> parse(InputStream is) throws IOException {
		Map<String, String> paramMap = new HashMap<String, String>();
		LineNumberReader lr = new LineNumberReader(new InputStreamReader(is));
		String inputLine = null;
		String method = null;
		String httpVersion = null;
		String uri = null;

		// read request line
		inputLine = lr.readLine();
		String[] requestCols = inputLine.split("\\s");
		method = requestCols[0];
		uri = requestCols[1];
		httpVersion = requestCols[2];
		System.out.println("http version:\t" + httpVersion);

		// parse GET param
		if (uri.contains("?")) {
			paramMap.putAll(parseParam(uri.split("\\?", 2)[1], false));
		}

		// read header
		while (StringUtils.isNotBlank(inputLine = lr.readLine())) {
			System.out.println("post header line:\t" + inputLine);
		}

		// read body - POST method
		if (method.toUpperCase().equals("POST")) {
			StringBuffer bodySb = new StringBuffer();
			char[] bodyChars = new char[1024];
			int len;

			// ready() make sure it will not block,
			while (lr.ready() && (len = lr.read(bodyChars)) > 0) {
				bodySb.append(bodyChars, 0, len);
			}
			paramMap.putAll(parseParam(bodySb.toString(), true));

			System.out.println("post body:\t" + bodySb.toString());
		}

		return paramMap;
	}

	@Override
	public Map<String, String> parseParam(String paramStr, boolean isBody) {
		String[] paramPairs = paramStr.trim().split("&");
		Map<String, String> paramMap = new HashMap<String, String>();

		String[] paramKv;
		for (String paramPair : paramPairs) {
			if (paramPair.contains("=")) {
				paramKv = paramPair.split("=");
				if (isBody) {
					// replace '+' to ' ', because in body ' ' is replaced by '+' automatically when post,
					paramKv[1] = paramKv[1].replace("+", " ");
				}
				paramMap.put(paramKv[0], paramKv[1]);
			}
		}

		return paramMap;
	}

	@Override
	public void response(OutputStream os, Map<String, String> paramMap) {
		String name = StringUtils.isBlank(paramMap.get("name")) ? "xxx" : paramMap.get("name");

		PrintWriter pw = null;
		pw = new PrintWriter(os);
		pw.println("HTTP/1.1 200 OK");
		pw.println("Content-type: text/html; Charset=UTF-8");
		pw.println("");
		pw.println("<h1>Hi <span style='color: #FFF; background: #000;'>" + name + "</span> !</h1>");
		pw.println("<h4>current date: " + new Date() + "</h4>");
		pw.println("<p>you can provide your name via a param called <span style='color: #F00; background: yellow;'>\"name\"</span>, in both GET and POST method.</p>");
		pw.flush();
	}

	@Override
	public void terminate() throws IOException {
		server.close();
	}

	/****** test - start ******/
	public static void main(String[] args) {
		testHttpServer();
	}

	// test http server,
	public static void testHttpServer() {
		try {
			HttpServer server = new SimpleHttpServer(9090, 1, "localhost");
			server.start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/****** test - end ******/
}