HTTP服务器(3)
功能完整的HTTP服务器
导语
这个一个功能完备的HTTP服务器。它可以提供一个完整的文档输,包括图像,applet,HTML文件,文本文件。它与SingleFileHttpServer非常相似,只不过它所关注的是GET请求的内容。它会根据GET请求的内容在自己的工作目录查找对应的资源,并将该资源返回给用户。这个服务是相当轻量级的。
主线程代码
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
public class JHTTP {
//开启日志
private static final Logger logger = Logger.getLogger(JHTTP.class.getCanonicalName());
//线程数
private static final int NUM_THREAD = 50;
//默认主页
private static final String INDEX_FILE = "index.html";
//服务器工作目录
private final File rootDirectory;
//端口号
private final int port;
/**
*
* @param _rootDirectory 工作目录
* @param _port 端口号
*/
public JHTTP(File _rootDirectory, int _port) {
if (!_rootDirectory.isDirectory())
throw new RuntimeException(_rootDirectory + "does not exist as a directory");
rootDirectory = _rootDirectory;
port = _port;
}
/**
* 启动服务器
* @throws IOException
*/
public void start() throws IOException {
ExecutorService pool = Executors.newFixedThreadPool(NUM_THREAD);
try (ServerSocket server = new ServerSocket(port)) {
logger.info("Accepting connection on port" + server.getLocalPort());
logger.info("Document Root: " + rootDirectory);
while (true) {
try {
Socket request = server.accept();
pool.execute(new RequestProcessor(rootDirectory, INDEX_FILE, request));
} catch (IOException e) {
logger.warning("Error accepting connection");
}
}
}
}
public static void main(String[] args) {
//设置工作目录
File docroot;
try {
docroot = new File(args[0]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Usage: java JHTTP docroot port");
return;
}
//设置监听端口号
int port;
try {
port = Integer.parseInt(args[1]);
if (port < 0 || port > 65535) port = 8080;
} catch (RuntimeException e) {
port = 8080;
}
try {
JHTTP webserver = new JHTTP(docroot, port);
webserver.start();
} catch (IOException e) {
logger.severe("Server cloud not start");
}
}
}
主线程代码比较简单,默认监听8080端口,将连接提交给工作线程来处理。
处理线程
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.URLConnection;
import java.nio.file.Files;
import java.util.Date;
import java.util.logging.Logger;
public class RequestProcessor implements Runnable {
private final static Logger logger = Logger.getLogger(RequestProcessor.class.getCanonicalName());
private File rootDirectory;
private String indexFileName = "index.html";
private Socket conn;
public RequestProcessor(File _rootDirectory, String _indexFileName,
Socket _conn) {
if (_rootDirectory.isFile())
throw new IllegalArgumentException("rootDirectory muse be a directory, not a file");
rootDirectory = _rootDirectory;
indexFileName = _indexFileName;
conn = _conn;
}
@Override
public void run() {
String root = rootDirectory.getPath();
try {
BufferedOutputStream raw = new BufferedOutputStream(conn.getOutputStream());
Writer out = new BufferedWriter(new OutputStreamWriter(raw, "utf-8"));
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String get = in.readLine();
if (get != null) {
logger.info(conn.getRemoteSocketAddress() + " " + get);
String[] pieces = get.split("\\s+");
String method = pieces[0];
String version = "";
if (method.equals("GET")) {
String fileName = pieces[1];
if (fileName.endsWith("/")) fileName += indexFileName;
String contentType = URLConnection.getFileNameMap().getContentTypeFor(root +fileName);
if (pieces.length > 2) {
version = pieces[2];
}
File theFile = new File(rootDirectory, fileName.substring(1, fileName.length()));
if (theFile.canRead() && theFile.getCanonicalPath().startsWith(root)) {
byte[] theData = Files.readAllBytes(theFile.toPath());
if (version.startsWith("HTTP/"))
sendHeader(out, "HTTP/1.1 200 OK", contentType, theData.length);
raw.write(theData);
raw.flush();
raw.close();
} else { //无法找到文件
String body = "<html><head><title>File not found</title></head><body>Error 404:文件未找到</body></html>";
if (version.startsWith("HTTP/"))
sendHeader(out, "HTTP/1.1 4O4 File Not Found", "text/html;charset=utf-8", body.getBytes("utf-8").length);
out.write(body);
out.flush();
out.close();
}
} else {
String body = "<html><head><title>File not found</title></head><body>Error 501:无法处理该请求</body></html>";
if (version.startsWith("HTTP/"))
sendHeader(out, "HTTP/1.1 5O1 Not Implemented", "text/html;charset=utf-8", body.getBytes("utf-8").length);
out.write(body);
out.flush();
out.close();
}
}
} catch (IOException e){
logger.warning("Error talking to " + conn.getRemoteSocketAddress());
} finally {
try {
conn.close();
} catch (IOException e) {}
}
}
private void sendHeader(Writer out, String responseCode, String contentType, int length) throws IOException {
out.write(responseCode + "\r\n");
out.write("Date: " + new Date() + "\r\n");
out.write("Server: JHTTP 2.0\r\n");
out.write("Content-Type: " + contentType + "\r\n");
out.write("Content-Length: " + length + "\r\n\r\n");
out.flush();
}
}
在处理线程中处理客户端的请求,通过解析GET请求的资源从本地中查找对应的资源。如果没有找的则返回404错误
HTTP服务器(3)的更多相关文章
- App开发:模拟服务器数据接口 - MockApi
为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...
- 闰秒导致MySQL服务器的CPU sys过高
今天,有个哥们碰到一个问题,他有一个从库,只要是启动MySQL,CPU使用率就非常高,其中sys占比也比较高,具体可见下图. 注意:他的生产环境是物理机,单个CPU,4个Core. 于是,他抓取了CP ...
- 闲来无聊,研究一下Web服务器 的源程序
web服务器是如何工作的 1989年的夏天,蒂姆.博纳斯-李开发了世界上第一个web服务器和web客户机.这个浏览器程序是一个简单的电话号码查询软件.最初的web服务器程序就是一个利用浏览器和web服 ...
- SignalR系列续集[系列8:SignalR的性能监测与服务器的负载测试]
目录 SignalR系列目录 前言 也是好久没写博客了,近期确实很忙,嗯..几个项目..头要炸..今天忙里偷闲.继续我们的小系列.. 先谢谢大家的支持.. 我们来聊聊SignalR的性能监测与服务器的 ...
- 使用 Nodejs 搭建简单的Web服务器
使用Nodejs搭建Web服务器是学习Node.js比较全面的入门教程,因为要完成一个简单的Web服务器,你需要学习Nodejs中几个比较重要的模块,比如:http协议模块.文件系统.url解析模块. ...
- 通过ProGet搭建一个内部的Nuget服务器
.NET Core项目完全使用Nuget 管理组件之间的依赖关系,Nuget已经成为.NET 生态系统中不可或缺的一个组件,从项目角度,将项目中各种组件的引用统统交给NuGet,添加组件/删除组件/以 ...
- 谈谈如何使用Netty开发实现高性能的RPC服务器
RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络,从远程计算机程序上请求服务,而不必了解底层网络技术的协议.说的再直白一点,就是客户端在不必知道 ...
- 游戏服务器菜鸟之C#初探一游戏服务
本人80后程序猿一枚,原来搞过C++/Java/C#,因为工作原因最后选择一直从事C#开发,因为读书时候对游戏一直比较感兴趣,机缘巧合公司做一个手游的项目,我就开始游戏服务器的折腾之旅. 游戏的构架是 ...
- 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查。。。
异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 无法向会话状态服务器发出会话状态请求.请确保 ASP.NET State Ser ...
- SQL Server 无法连接到服务器。SQL Server 复制需要有实际的服务器名称才能连接到服务器。请指定实际的服务器名称。
异常处理汇总-数据库系列 http://www.cnblogs.com/dunitian/p/4522990.html SQL性能优化汇总篇:http://www.cnblogs.com/dunit ...
随机推荐
- AWS系列-AWS EC2实例类型改配(机器配置升级)
1.1 EC2实例升级需要先把升级的实例停机才能升级 1.2 如图选择需要升级的EC2,点击操作,实例设置,更改实例类型 1.3 选择你要想的配置,点击应用 1.4 启动EC2实例即可
- oracle11g安装完成后修改字符集
author : headsen chen date:2018-05-10 10:27:16 oracle11g完成安装后,由于默认安装的时候无法指定字符集,所以手动修改字符集和10g版本一样的字符 ...
- iermu爱耳目
百度推出720P 云直播摄像头 查看直播请点击 直播 互联网网盘新动向实现初见端倪,之前写过一篇关于互联网网盘的思考. 我只是仅仅有想法而已,百度已经实现了一部分. 具体功能参见http://www. ...
- Jsp 公用标签库
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix=" ...
- react-native 学习(三)
上一次讲到了react-native 的配置环境 和 如何去进行调试,这一次我们说一说,关于react-native的 样式兼容问题. 由于iphonex的发售,在兼容的时候,我门也需要去考虑ipho ...
- 让IIS8支持WCF的最简单方法
以前在IIS8中使用WCF时,总是参考在IIS8添加WCF服务支持这篇博文进行手工设置: 1. 首先添加MIME类型:扩展名“.svc”,MIME类型 “application/octet-strea ...
- Cmake Make makefile GNU autotools
个人总结 首先makefile是由make来编译,而makefile的生成可以由GUN autotools和CMake来实现,但前者没有CMake的CMakelist.txt直观,所以我们一般用CMa ...
- 2017-2018-2 20165330实验二《Java面向对象程序设计》实验报告
实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步骤 (一)单元测试 三种代码 伪代码:从意图层面来解 ...
- IOUtils方式上传下载文件
package com.css.hdfs04; import java.io.File; import java.io.FileInputStream; import java.io.FileOutp ...
- java基础07 循环结构
public class While02 { public static void main(String[] args) { /** * while(循环条件){ * 循环体(循环操作) * } * ...