二、socket编写简单BIO的HTTP服务器
一、目标
诸如tomcat等web服务器中间件简化了我们web的开发成本,但有时候我们或许并不需要这么一个完备的服务器,只是希望做一个简单地处理或者做特殊用途的服务器。
本文将提供一个HTTP的服务器示例,采用Java的ServerSocket进行编码。随着计算机硬件的提升,以及Java地不断优化,使用Java网络编程实现web服务器在实际性能上已经开始可以跟C进行竞争。
二、代码示例
以下代码分为两块:
1)HttpServer:主要包含一个ServerSocket,用于接收客户端请求。并通过线程池将请求从主线程剥离,分散到各个线程中去处理;
2)RequestHandler:实现了Runnable接口,将获取一个线程来处理各个请求;流的读取和响应遵循HTTP协议。
注意:编写Http服务器和一般的socket程序并没有太大不同,但是你需要遵循HTTP协议,这样对于采用HTTP协议的客户端或者其它服务器就可以直接进行HTTP请求来通讯。
HttpServer
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
/**
* Http服务器端示例,端口设置为8080,编码设置为UTF-8
* @author lay
* @date 2019-01-01
*/
public class HttpServer {
private static final int port = 8080;
/**
* 启动HTTP服务器
*/
public void start() throws IOException {
// 初始化线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// 初始化服务器socket
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("ServerSocket启动完成");
while (true) {
// 阻塞等待socket连接
System.out.println("等待socket");
Socket socket = serverSocket.accept();
// 提交至线程池处理
executor.submit(new RequestHandler(socket));
System.out.println("提交线程池处理请求");
}
}
public static void main(String[] args) {
try {
new HttpServer().start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
RequestHandler
import java.io.*;
import java.net.Socket;
/**
* 请求处理类
* @author lay
* @date 2019-01-01
*/
public class RequestHandler implements Runnable {
/**
* HTTP响应头
*/
private static final String response = "http/1.1 200 ok";
private static final String splitStr = "\r\n";
private Socket socket;
private BufferedReader reader;
private BufferedWriter writer;
public RequestHandler(Socket socket) throws IOException {
this.socket = socket;
this.reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
this.writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
}
/**
* 响应结果
* @param content 响应内容
* @throws IOException IO异常抛出
*/
public void sendResponse(String content) throws IOException {
writer.write(String.format("%s%s", response, splitStr));
writer.write(splitStr);
writer.write(content);
}
/**
* 获得请求
* @return 请求文本
* @throws IOException IO异常抛出
*/
public String getRequest() throws IOException {
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(splitStr);
// 空字符串
if (line.isEmpty()) {
break;
}
}
System.out.println("request:\r\n" + stringBuilder);
return stringBuilder.toString();
}
@Override
public void run() {
try {
String request = getRequest();
// 这里直接把请求数据响应回去
sendResponse(request);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
请求处理器这里直接将请求的HTTP内容返回回去了,如果你使用浏览器请求8080端口,你会看到如下内容:

不过浏览器会默认请求一个icon,所以针对一个URL地址会有两个请求

你可以在ico请求的时候返回一个二进制的ico文件流,它将显示在浏览器的tab上。
扩展点:
1)我们可以像tomcat一样去支持Java Servlet API
2)支持如GET、POST、PUT、DELETE等restful请求
3)将程序配置进行XML配置
4)增加管理界面
5)请求跟踪处理
6)缓存、非阻塞IO、通道来增加性能
二、socket编写简单BIO的HTTP服务器的更多相关文章
- ROS学习(十二)—— 编写简单的消息发布器和订阅器(C++)
一.创建发布器节点 1 节点功能: 不断的在ROS网络中广播消息 2 创建节点 (1)打开工作空间目录 cd ~/catkin_ws/src/beginner_tutorials 创建一个发布器节点( ...
- 关于Socket编写简单聊天工具的总结(原创)
这段时间再看socket编程,虽然现在是刚刚接触,但是还是忍不住想写一篇总结,来激励自己努力学习,写的不好的地方,还请大家指教啊! 下面针对一个简单的发送消息和文件的程序说说吧. 首先是服务器需要 ...
- socket编写简单回显server
socket在公司代码中应用比较广,比如接口调用的IPCRPC机制,经常看到这样的代码,但是一直也没有动手写过. 在某个比较大的进程中创建一个子进程,由于父子进程复制会浪费内存,可以将创建进程的命令通 ...
- Linux 字符设备驱动开发基础(二)—— 编写简单 PWM 设备驱动【转】
本文转载自:https://blog.csdn.net/zqixiao_09/article/details/50858776 版权声明:本文为博主原创文章,未经博主允许不得转载. https: ...
- 小鸟初学Shell编程(二)编写简单的Shell脚本
Shell脚本 编写Python.PHP脚本通常需要掌握语言的函数,那么Shell脚本则不需要,只需要掌握Linux命令就可以编写Shell脚本,因为Shell脚本就是由多个Linux命令组成,通过将 ...
- C#中使用Socket实现简单Web服务器
上一篇博客中介绍了怎样使用socket访问web服务器.关键有两个: 熟悉Socket编程: 熟悉HTTP协议. 上一篇主要是通过socket来模拟浏览器向(任何)Web服务器发送(HTTP)请求,重 ...
- 运用socket实现简单的服务器客户端交互
Socket解释: 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket的英文原义是“孔”或“插座”.作为BSD UNIX的进程通信机制,取后一种意 ...
- java Socket实现简单在线聊天(二)
接<java Socket实现简单在线聊天(一)>,在单客户端连接的基础上,这里第二步需要实现多客户端的连接,也就需要使用到线程.每当有一个新的客户端连接上来,服务端便需要新启动一个线程进 ...
- SLAM+语音机器人DIY系列:(二)ROS入门——5.编写简单的消息发布器和订阅器
摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...
随机推荐
- datatime模块
https://www.cnblogs.com/cindy-cindy/p/6720196.html
- 【Oracle 12c】CUUG OCP认证071考试原题解析(30)
30.choose the best answer Examine the commands used to create DEPARTMENT_DETAILS and COURSE_DETAILS: ...
- 【OCP认证12c题库】CUUG 071题库考试原题及答案(28)
28.choose the best answer Evaluate the following SQL statement: SQL> SELECT promo_id, promo_categ ...
- “全栈2019”Java第九十七章:在方法中访问局部内部类成员详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- C++中重载、覆盖和隐藏
一,多态性 1,(1)声明了基类的指针,该指针指向基类,该指针永远调用自己的成员函数,不管函数是否为虚函数. (2)声明了派生类的指针,该指针指向该派生类,该指针永远调用自己的成员函数,不管函数是否为 ...
- Linux系统NAT模式下设置网络网关
1.配置Vm网络编辑器 2.配置固定IP地址 命令:vi /etc/sysconfig/network-scripts/ifcfg-ens33 #下面内容直接复制进去,如果有重复的可以去除 TYPE= ...
- 何在不联网的情况下ping通主机与虚拟机
选择NAT模式,VM对windows选择ping操作时选择VMnet8的IP地址.
- Python基础部分的疑惑解析(2)
变量: 变量名由 字母.数字.下划线构成,数字不能做为开头 不能用关键字:另外一些内置的方法也别用 推荐使用下划线命名间两个单词user_id 变量在最后底层处理的时候没什么意义,但是在命名的时候有利 ...
- 生成allure测试报告之后,服务器端口无法访问查看生成的report,可能是这样引起的。
1. 检查防火墙 2. 如果机器有安装ADsafe,请关闭adsafe后重试
- 通过源码看原理之 selenium
# selenium的历史1. selenium1.x:这个时候的selenium,使用的是JavaScript注入技术与浏览器打交道,需要Selenium RC启动一个Server,将操作Web元素 ...