java中如何写一个http服务_Java实现一个简易HTTP服务器(三)

从InputStream读取数据,构造Request。Request包含Http请求的参数。

public class Request {

public String method; // 请求方法

public String path; // 请求路径

public String portal; // 协议名称

public Map 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 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 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> entries = map.entrySet().iterator();

while (entries.hasNext()) {

Entry 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(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();

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值