java 的http 服务器_java实现的HTTP简易服务器

程序有点BUG,欢迎高手指点,为啥不同的浏览器差别这么大?

运行服务器端程序后,在浏览器分别输入如下请求路径观察效果(我的服务器资源默认路径设置的是F:/project目录)。

http://localhost

http://localhost/myfile.txt

/*

* 模拟一个HTTP服务器的实现

* 客户端(浏览器)请求服务器的文件,服务器端程序接受连接并处理,将相应的数据写入socket,发送给客户端

* 本Web服务器将入站连接放入池中,由一个RequestProcessor类实例从池中移走连接并进行处理

*/

import java.io.*;

import java.net.*;

public class JHTTP extends Thread{

private File documentRootDirectory;

private String indexFileName="index.html";

private ServerSocket server;

private int numThreads =50;//设置服务器启动的线程数

public JHTTP(File documentRootDirectory,int port,String indexFileName) throws IOException{

if(!documentRootDirectory.isDirectory()){

throw new IOException(documentRootDirectory+" does not exist as a directory");

}

this.documentRootDirectory=documentRootDirectory;

this.indexFileName=indexFileName;

this.server=new ServerSocket(port);

}

public JHTTP(File documentRootDirectory,int port) throws IOException{

this(documentRootDirectory,port,"index.html");

}

public JHTTP(File documentRootDirectory) throws IOException{

this(documentRootDirectory,80,"index.html");

}

public void run(){

//开启处理请求的线程,该线程会从socket池中取出一个socket连接,进行数据传输

for(int i=0;i

Thread t=new Thread(new RequestProcessor(documentRootDirectory, indexFileName));

t.start();

}

System.out.println("Accepting connections on port "+server.getLocalPort()+"...");

System.out.println("Document Root:"+documentRootDirectory);

//服务器不停地接受请求

while(true){

try {

Socket connection=server.accept();

RequestProcessor.processRequest(connection);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

public static void main(String[] args) {

File docRoot;//得到文档根

docRoot=new File("F:\\project");

//设置服务器的监听端口

int port;

port=80;

try {

JHTTP webServer=new JHTTP(docRoot,port);

webServer.start();

} catch (IOException e) {

System.out.println("Server could not start because of an "+e.getClass());

System.out.println(e);

}

}

}

//具体处理连接的线程类

import java.util.Date;

import java.util.LinkedList;

import java.util.List;

import java.util.StringTokenizer;

import java.io.*;

import java.net.Socket;

public class RequestProcessor implements Runnable {

private static List pool = new LinkedList();

private File documentRootDirectory;

private String indexFileName = "index.html";

public RequestProcessor(File documentRootDirectory, String indexFileName) {

if (documentRootDirectory.isFile()) {

throw new IllegalArgumentException(

"documentRootDirectory must be a directory,not a file");

}

this.documentRootDirectory = documentRootDirectory;

// 返回此抽象路径名的规范形式

try {

this.documentRootDirectory = documentRootDirectory

.getCanonicalFile();

} catch (IOException e) {

System.out.println(e);

}

if (indexFileName != null) {

this.indexFileName = indexFileName;

}

}

public static void processRequest(Socket request) {

// 将对应于每一个客户端的socket连接放入池中,通知线程来处理他们

synchronized (pool) {

pool.add(pool.size(), request);

pool.notifyAll();

}

}

@Override

public void run() {

// 执行安全性检查,请求的文档不能超过根目录

String root = documentRootDirectory.getPath();

// 由于采用线程池的策略,所以说线程要不停地执行,以处理客户端的请求池(socket池)中的连接

while (true) {

Socket connection;

synchronized (pool) {

while (pool.isEmpty()) {

try {

pool.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

connection = (Socket) pool.remove(0);

}

// 通过socket这个中介进行服务器客户端的数据交换

try {

OutputStream raw;

raw = new BufferedOutputStream(connection.getOutputStream());

Writer out = new OutputStreamWriter(raw);

Reader in = new InputStreamReader(new BufferedInputStream(

connection.getInputStream()), "ASCII");

// 存储客户端请求的第一行数据

StringBuffer requestLine = new StringBuffer();

int c;

while (true) {

c = in.read();

if (c == '\r' || c == '\n')

break;

requestLine.append((char) c);

}

String get = requestLine.toString();

System.out.println(get);// 记录请求的头一行(要对头行进行一些分解,如下)

StringTokenizer st = new StringTokenizer(get);

String method = st.nextToken();

String version = "";

// 本案例目前只处理GET请求

String filename;

String contentType;

if (method.equals("GET")) {

filename = st.nextToken();

if (filename.endsWith("/"))

filename += indexFileName;

contentType = guessContentTypeFromName(filename);

if (st.hasMoreTokens()) {

version = st.nextToken();

}

File theFile = new File(documentRootDirectory,

filename.substring(1, filename.length()));

if (theFile.canRead()

&& theFile.getCanonicalPath().startsWith(root)) {

DataInputStream fis = new DataInputStream(

new BufferedInputStream(new FileInputStream(

theFile)));

byte[] theData = new byte[(int) theFile.length()];

fis.readFully(theData);

fis.close();

if (version.startsWith("HTTP ")) {// 发送MIME首部

out.write("HTTP/1.0 200 OK\r\n");// HTTP协议规定的头格式,就是要求回车换行,就必须是\r\n

Date now = new Date();

out.write("Date:" + now + "\r\n");

out.write("Server:JHTTP/1.0\r\n");

out.write("Content-Length:" + theData.length

+ "\r\n");

out.write("Content-Type:" + contentType

+ "\r\n\r\n");

out.flush();// 切记结束的时候要刷新,写入缓冲区剩余数据

}

// 发送实际请求的文件(可能是图片或其它二进制文件)

raw.write(theData);

raw.flush();

} else {// 无法找到文件

if (version.startsWith("HTTP ")) {// 发送MIME首部

out.write("HTTP/1.0 404 File Not Found ON MyServer\r\n");// HTTP协议规定的头格式,就是要求回车换行,就必须是\r\n

Date now = new Date();

out.write("Date:" + now + "\r\n");

out.write("Server:JHTTP/1.0\r\n");

out.write("Content-Type:text/html\r\n\r\n");

}

out.write("\r\n");

out.write("

File not found\r\n");

out.write("\r\n");

out.write("

");

out.write("

HTTP Error 404:File not found\r\n");

out.write("\r\n");

out.flush();

}

} else {// 不是'GET'方法

if (version.startsWith("HTTP ")) {// 发送MIME首部

out.write("HTTP/1.0 501 Not Implemented\r\n");// HTTP协议规定的头格式,就是要求回车换行,就必须是\r\n

Date now = new Date();

out.write("Date:" + now + "\r\n");

out.write("Server:JHTTP/1.0\r\n");

out.write("Content-Type:text/html\r\n\r\n");

}

out.write("\r\n");

out.write("

Not Implemented\r\n");

out.write("\r\n");

out.write("

");

out.write("

HTTP Error 501:Not Implemented\r\n");

out.write("\r\n");

out.flush();

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

try {

connection.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

public static String guessContentTypeFromName(String name) {

if (name.endsWith(".htm") || name.endsWith(".html")) {

return "text/html";

} else if (name.endsWith(".txt") || name.endsWith(".java")) {

return "text/plain";

} else if (name.endsWith(".class")) {

return "application/octet-stream";

} else if (name.endsWith(".gif")) {

return "image/gif";

} else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {

return "image/jpeg";

} else if (name.endsWith(".mp3")) {

return "audio/mpeg";

} else {

return "text/plain";

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值