单文件服务器

导语

在研究HTTP服务器时,我们可以从一个单文件服务器开始。无论接受到什么请求,这个服务器始终发送同一个文件。下面是示例代码,绑定的端口,发送的文件名以及文件的编码从命令行读取。如果省略端口则假定为端口80,如果省略编码方式默认8080

示例代码

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Logger; public class SingleHttpServer {
private static final Logger logger = Logger.getLogger("SingleFileHttpServer");
private static Handler handler;
private final byte[] content;
private final byte[] header;
private final int port;
private final String encoding; public SingleHttpServer(String _content, String _encoding, String mimeType, int _port) {
this(_content.getBytes(), _encoding, mimeType, _port);
} public SingleHttpServer(byte[] _content, String _encoding, String mimeType, int _port) {
try {
handler = new FileHandler("SingleFileHttpServer.log");
} catch (Exception e) {
throw new RuntimeException("cannot create log file!");
}
logger.addHandler(handler);
content = _content;
encoding = _encoding;
String header1 = "HTTP/1.1 200 OK\r\n"
+ "Server: OneFile\r\n"
+ "Content-length: "+ content.length +"\r\n"
+ "Content-Type: " + mimeType + ";charset=" + encoding + "\r\n\r\n";
header = header1.getBytes(Charset.forName("utf-8"));
port = _port;
} public void start() {
ExecutorService pool = Executors.newFixedThreadPool(100);
try (ServerSocket server = new ServerSocket(port)) {
logger.info("Accepting connections on port " + server.getLocalPort());
logger.info("Data to be sent:");
logger.info(new String(content, encoding));
while (true) {
Socket socket = server.accept();
pool.execute(new HttpHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
}
} private class HttpHandler implements Runnable { private final Socket socket; public HttpHandler(Socket _socket) {
socket = _socket;
} @Override
public void run() {
try (
OutputStream out = new BufferedOutputStream(socket.getOutputStream());
InputStream in = new BufferedInputStream(socket.getInputStream());
) {
StringBuilder request = new StringBuilder(80);
while (true) {
int c = in.read();
if (c == '\r' || c == '\n' || c == -1)break;
request.append((char)c);
}
if (request.toString().indexOf("HTTP/") != -1) {
out.write(header);
}
out.write(content);
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} public static void main(String[] args) { //设置端口
int port;
try{
port = Integer.parseInt(args[2]);
if (port < 1 || port > 65535)
port = 8080;
} catch (RuntimeException e) {
//如果参数中没有端口,则会发生数组越界,所以需要捕获
port = 8080;
}
//设置编码方式
String encoding = "UTF-8";
if (args.length >= 2) encoding = args[1]; try {
Path path = Paths.get(args[0]).toAbsolutePath();
byte[] data = Files.readAllBytes(path);
String contentType = URLConnection.getFileNameMap().getContentTypeFor(path.toString());
SingleHttpServer server = new SingleHttpServer(data, encoding, contentType, port);
server.start();
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println("Usage: java SingleHttpServer filename [encoding [port]]");
} catch (IOException e) {
logger.severe(e.getMessage());
}
}
}

main()方法中是从命令行读取参数。从第一个命令行读取提供的文件名。如果没有指定文件或者如果文件无法打开,就显示一条错误信息,程序推出。假定文件能够读取,就是用java7引入的Path和Files类将其内容读入byte数组。URLConnection类对文件的内容类型做出合理的猜测,将猜测的结果保存到contentTyep变量中。接下来读取第二个参数,如果没有则指定编码方式为UTF-8。

HTTP服务器(1)的更多相关文章

  1. App开发:模拟服务器数据接口 - MockApi

    为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现Moc ...

  2. 闰秒导致MySQL服务器的CPU sys过高

    今天,有个哥们碰到一个问题,他有一个从库,只要是启动MySQL,CPU使用率就非常高,其中sys占比也比较高,具体可见下图. 注意:他的生产环境是物理机,单个CPU,4个Core. 于是,他抓取了CP ...

  3. 闲来无聊,研究一下Web服务器 的源程序

    web服务器是如何工作的 1989年的夏天,蒂姆.博纳斯-李开发了世界上第一个web服务器和web客户机.这个浏览器程序是一个简单的电话号码查询软件.最初的web服务器程序就是一个利用浏览器和web服 ...

  4. SignalR系列续集[系列8:SignalR的性能监测与服务器的负载测试]

    目录 SignalR系列目录 前言 也是好久没写博客了,近期确实很忙,嗯..几个项目..头要炸..今天忙里偷闲.继续我们的小系列.. 先谢谢大家的支持.. 我们来聊聊SignalR的性能监测与服务器的 ...

  5. 使用 Nodejs 搭建简单的Web服务器

    使用Nodejs搭建Web服务器是学习Node.js比较全面的入门教程,因为要完成一个简单的Web服务器,你需要学习Nodejs中几个比较重要的模块,比如:http协议模块.文件系统.url解析模块. ...

  6. 通过ProGet搭建一个内部的Nuget服务器

    .NET Core项目完全使用Nuget 管理组件之间的依赖关系,Nuget已经成为.NET 生态系统中不可或缺的一个组件,从项目角度,将项目中各种组件的引用统统交给NuGet,添加组件/删除组件/以 ...

  7. 谈谈如何使用Netty开发实现高性能的RPC服务器

    RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络,从远程计算机程序上请求服务,而不必了解底层网络技术的协议.说的再直白一点,就是客户端在不必知道 ...

  8. 游戏服务器菜鸟之C#初探一游戏服务

    本人80后程序猿一枚,原来搞过C++/Java/C#,因为工作原因最后选择一直从事C#开发,因为读书时候对游戏一直比较感兴趣,机缘巧合公司做一个手游的项目,我就开始游戏服务器的折腾之旅. 游戏的构架是 ...

  9. 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查。。。

    异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 无法向会话状态服务器发出会话状态请求.请确保 ASP.NET State Ser ...

  10. SQL Server 无法连接到服务器。SQL Server 复制需要有实际的服务器名称才能连接到服务器。请指定实际的服务器名称。

    异常处理汇总-数据库系列  http://www.cnblogs.com/dunitian/p/4522990.html SQL性能优化汇总篇:http://www.cnblogs.com/dunit ...

随机推荐

  1. 通过三个DEMO学会SignalR的三种实现方式

    一.理解SignalR ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信(即:客户端(Web页面)和服务器端可以互相实时的通知消息 ...

  2. domReady的实现

    我们都知道JQ的 $(document).ready(fn) 方法.可以在页面准备就绪后才执行脚本,该方法相比传统的window.onload 事件,它的优势体现于onload事件是需要等到页面中所有 ...

  3. [C1] C1ComboBox 的非编辑状态优化

    一.前言 先看看 WPF 自带的 ComboBox 在非编辑状态,自定义 ItemTemplate 的情况下,效果如下图所示: 其当前选中的项(红框内)与自定义的 ItemTemplate 一样: 但 ...

  4. Sql常用语句(3)

    --显示sql server现有的所有数据库 exec sp_helpdb --查看数据表设置的约束 exec sp_helpconstraint SubjectType --update selec ...

  5. 使用Expression实现数据的任意字段过滤(2)

    上一篇<使用Expression实现数据的任意字段过滤(1)>, 我们实现了通过CriteriaCollectionHandler对象来处理集合数据过滤.通过适当的扩展, 应该可以满足一般 ...

  6. asp.net MVC4——省市三级联动

    controller: public ActionResult GetCity(string id) { AreaService _areaSvc = new AreaService(); List& ...

  7. SVG坐标系统

    SVG的画布.画布视区(viewBox).浏览器视窗的概念 画布 画布是绘制SVG内容的一块区域,理论上在所有维度上都是无限的.(也有人称为"SVG世界",但我觉得叫画布比较合适) ...

  8. View and Data API Tips : Conversion between DbId and node

    By Daniel Du In View and Data client side API, The assets in the Autodesk Viewer have an object tree ...

  9. Android EventBus 3.0.0 使用总结

    转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6039221.html 本文出自[赵彦军的博客] 前言 EventBus框架 EventBus是一个通用的叫法 ...

  10. iOS 正确选择图片加载方式

    正确选择图片加载方式能够对内存优化起到很大的作用,常见的图片加载方式有下面三种: //方法1 UIImage *imag1 = [UIImage imageNamed:@"image.png ...