Java实现一个简易HTTP服务器
Posted 臭蛋1999
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java实现一个简易HTTP服务器相关的知识,希望对你有一定的参考价值。
从InputStream读取数据,构造Request。Request包含Http请求的参数。
public class Request {
public String method; // 请求方法
public String path; // 请求路径
public String portal; // 协议名称
public Map<String, String> map; // 请求头中的附加参数
public String payload; // 请求体
private int BUFFER_LEN = 10240;
public Request(InputStream in) throws IOException {
byte[] buf = new byte[BUFFER_LEN];
int len = in.read(buf);
String reqString = new String(buf, 0, len);
String raw = reqString;
int i = 0, j = 0;
// 获取请求方式
for (; i < raw.length(); i++)
if (raw.charAt(i) == ‘ ‘) {
this.method = raw.substring(j, i);
break;
}
j = ++i;
// 获取请求路径
for (; i < raw.length(); i++)
if (raw.charAt(i) == ‘ ‘) {
this.path = raw.substring(j, i);
break;
}
j = ++i;
// 获取协议版本
for (; i < raw.length(); i++)
if (raw.charAt(i) == ‘\r‘) {
this.portal = raw.substring(j, i);
break;
}
j = (i += 2);
this.map = new HashMap<String, String>();
String key = "", value = "";
while (i < raw.length()) {
if (raw.charAt(i) != ‘:‘) {
i++;
} else {
key = raw.substring(j, i);
j = (i += 2);
while (i != raw.length() && raw.charAt(i) != ‘\r‘)
i++;
value = raw.substring(j, i);
map.put(key, value);
if (i == raw.length()) {
break;
} else {
j = (i += 2);
if (raw.charAt(i) == ‘\r‘) {
payload = raw.substring(i + 2);
}
}
}
}
}
@Override
public String toString() {
return "Request [method=" + method + ", path=" + path + ", portal=" + portal + ", map=" + map + ", payload="
+ payload + "]";
}
}
Response 向输出流中写入参数。类中定义了部分用到的方法。
package cdbb.httpd;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class Response {
private OutputStream out;
public String portal;
public String status;
public String statusDescribe;
public Map<String, String> map;
public Response(OutputStream out, String portal, String status, String statusDescribe) {
this.out = out;
this.portal = portal;
this.status = status;
this.statusDescribe = statusDescribe;
}
public void writeHeaderAndBody(byte[] b, int off, int len) {
this.writeHeader();
this.writeBytes(b, off, len);
}
public void addHeader(String key, String value) {
this.map.put(key, value);
}
public void delHeader(String key) {
if (this.map.containsKey(key))
this.map.remove(key);
}
public void editHeader(String key, String value) {
if (this.map.containsKey(key))
this.map.replace(key, value);
}
public void writeHeader() {
try {
String tmp = portal + " " + status + " " + statusDescribe + "\n";
this.writeBytes(tmp.getBytes(), 0, tmp.length());
if (map != null) {
Iterator<Map.Entry<String, String>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Entry<String, String> entry = entries.next();
String s = entry.getKey() + " " + entry.getValue() + "\n";
this.writeBytes(s.getBytes(), 0, s.length());
}
}
this.out.write(‘\n‘);
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeBytes(byte[] b, int off, int len) {
try {
this.out.write(b, off, len);
} catch (IOException e) {
e.printStackTrace();
}
}
}
在浏览器和服务端建立起tcp连接后获得socket,一个连接对应一个socket。socket调用Request和Response处理请求
package cdbb.httpd;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class Handler implements Runnable {
public Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
Request req = new Request(in);
System.out.println(req);
if ("/".equals(req.path)) {
req.path = "index.html";
}
if ("/favicon.ico".equals(req.path)) {
req.path = "favicon.ico";
}
File file = new File(req.path);
InputStream fin = new FileInputStream(file);
int len = 0;
byte[] buf = new byte[1024];
OutputStream out = socket.getOutputStream();
Response res = new Response(out, "HTTP/1.1", "200", "OK");
res.writeHeader();
while ((len = fin.read(buf)) > 0)
res.writeBytes(buf, 0, len);
socket.close();
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
建立和浏览器的连接,并采用线程池技术调用Handler进行具体的处理
package cdbb.httpd;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author cdbb
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(80);
System.out.println("Server started at " + new Date() + "\n");
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 5, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(5), Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try {
while (true) {
// 通信socket的获得
Socket socket = serverSocket.accept();
threadPoolExecutor.execute(new Handler(socket));
}
} catch (Exception e) {
e.printStackTrace();
serverSocket.close();
}
}
}
以上是关于Java实现一个简易HTTP服务器的主要内容,如果未能解决你的问题,请参考以下文章