当前位置:网站首页>Handwritten a simple web server (B/S architecture)
Handwritten a simple web server (B/S architecture)
2022-07-31 22:49:00 【IT_WEH_coder】
涉及WebServer-related technologies
IO流、Socket网络编程、HTTP协议、文件、多线程(同时处理多个浏览器的请求)、List集合
1 webHow the application server works:
连接过程:WebThe connection established between the server and its browser,Determine whether the connection between the two is successful;If the user can find and open a virtual file socket,说明WebA connection is successfully established between the server and its browser.
请求过程:Web浏览器利用socketFiles make various requests to their servers.
Get the address of the requested resource
Make corresponding processing according to whether it is a static resource or a dynamic resource
响应过程:The request made during the request process is made by usingHTTP协议传输到Web服务器,Then perform task processing.
关闭连接:After the response process is complete,WebThe process by which a server disconnects from its browser.
2 代码展示
(1)Main类
package com.weh;
import com.weh.httpserver.MyHttpServer;
public class Main {
// 开启多线程
public static void main(String[] args) {
new Thread(new MyHttpServer()).start();
}
}
(2)MyHttpServer类
package com.weh.httpserver;
import com.weh.response.MyResponse;
import com.weh.request.MyRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/* * 1.通过Runnable接口的实现类,来开启线程 * 2.Create and start the server * 3.Implement the connection communication between the server and the client * */
public class MyHttpServer implements Runnable{
public static final int port = 8080; //服务器端口号
public static final String WEB_ROOT=System.getProperty("user.dir")+
File.separator+ "webapps"; //The current file directory path of the server
@Override
public void run() {
ServerSocket serverSocket=null;
Socket socket;
InputStream input=null;
OutputStream output=null;
try {
System.out.println("Web服务器已开启");
serverSocket = new ServerSocket(port); //Pass in the port number and create the server
} catch (Exception e) {
System.exit(0);
}
//The server communicates with the client browser
while(true){
try {
socket=serverSocket.accept();//请求
input=socket.getInputStream();//Get the information sent by the client
output=socket.getOutputStream();
MyRequest request=new MyRequest(input); //数据处理
request.parse();
MyResponse response=new MyResponse(output);
response.setMyRequest(request);
response.sendStaticResource();//发送
} catch (Exception e) {
e.printStackTrace();
continue;
}finally {
// 释放资源
release(input,output);
}
}
}
// 释放资源
public void release(InputStream inputStream,OutputStream outputStream){
try {
if(inputStream != null) {
inputStream.close();
}
if(outputStream != null){
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
(3)MyRequest类
package com.weh.request;
import java.io.InputStream;
/* * 自定义MyRequest类 * 1.It mainly processes the information sent by the client and outputs it * 2.Get the name of the file to which the client switches * */
public class MyRequest {
private InputStream input;
private String uri;
public MyRequest(InputStream input){
this.input=input;
}
// 输出客户端发过来的信息
public void parse(){
StringBuffer request=new StringBuffer(2048);
int len;
byte[] buffer=new byte[2048];
try {
len=input.read(buffer);
} catch (Exception e) {
len=-1;
}
for(int j=0;j<len;j++){
request.append((char)buffer[j]);
}
System.out.print(request.toString());
parseUri(request.toString());
}
// Get the switched filename
public void parseUri(String srt){
int index1,index2;
index1=srt.indexOf(" ");
if(index1!=-1){
index2=srt.indexOf(" ",index1+1);
if(index2>index1){
setUri(srt.substring(index1+1,index2));
}
}
}
public void setUri(String uri) {
this.uri = uri;
}
public String getUri(){
return this.uri;
}
}
(4)MyResponse类
package com.weh.response;
import com.weh.httpserver.MyHttpServer;
import com.weh.request.MyRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
/* * 自定义MyResponse类 * 1.向SocketThe result of writing the request to the browser to respond to the output stream * 2.Gets all files in the current directory and creates an array of file types * 3.Reading and forwarding of data * */
public class MyResponse {
private static final int BUFFER_SIZE=1024;
MyRequest request;
OutputStream output;
FileInputStream fis=null;
PrintWriter printWriter =null;
public MyResponse(OutputStream output){
this.output=output;
}
public void setMyRequest(MyRequest request){
this.request=request;
}
public void sendStaticResource()throws IOException{
byte[] bytes=new byte[BUFFER_SIZE];
try {
printWriter = new PrintWriter(output); //创建缓冲字符输出流
File file=new File(MyHttpServer.WEB_ROOT+request.getUri());
if(file.exists()){
//判断文件目录是否存在
//向SocketThe result of writing the request to the browser to respond to the output stream
printWriter.println("HTTP/1.1 200 OK");
printWriter.println("Content-Type:text/html;charset=UTF-8");
printWriter.println();
// 判断文件是否为普通文件
if(file.isFile()){
fis=new FileInputStream(file.getPath()); //创建文件字节输入流
fis.read(bytes); //read direct stream
printWriter.write(new String(bytes));
// Determines whether the file is a file directory
}else if(file.isDirectory()){
List<File> list= Arrays.asList(new File(file.getPath()).listFiles());//Gets all files in the current directory and creates an array of file types
for(File filename : list){
//数组遍历
if(filename.getName().indexOf(".htm")>0) {
//判断是否含有.htm的字符的文件
printWriter.write("<li>");
printWriter.write("<a style='text-decoration:blink;' href='" +
"./" + filename.getName() + "'>"
+ filename.getName() + "</a>");
printWriter.write("</li>");
}
}
}
// 若该文件不存在,则输出信息 File Not Found
}else{
printWriter.println("HTTP/1.1 404 File Not Found");
printWriter.println("Content-Type:text/html;charset=UTF-8");
printWriter.println("Content-Length:23");
printWriter.println();
printWriter.write("<h1>File Not Found</h1>");
}
printWriter.flush();//不返回任何值,Only used to refresh the stream
} catch (Exception e) {
e.printStackTrace();
}finally{
if(printWriter!=null){
printWriter.close();
}
if(output!=null){
output.close();
}
if(fis!=null){
fis.close();
}
}
}
}
3项目的结构设计
4 效果展示
边栏推荐
- 程序进程和线程(线程的并发与并行)以及线程的基本创建和使用
- BOW/DOM (top)
- Bionic caterpillar robot source code
- Daily practice——Randomly generate an integer between 1-100 and see how many times you can guess.Requirements: The number of guesses cannot exceed 7 times, and after each guess, it will prompt "bigger"
- Embedded development has no passion, is it normal?
- 无状态与有状态的区别
- sqlite3 simple operation
- In Golang go-redis cluster mode, new connections are constantly created, and the problem of decreased efficiency is solved
- SQL注入 Less38(堆叠注入)
- 嵌入式开发没有激情了,正常吗?
猜你喜欢
In Golang go-redis cluster mode, new connections are constantly created, and the problem of decreased efficiency is solved
TestCafeSummary
A high-quality WordPress download site template theme developed abroad
网易云信圈组上线实时互动频道,「破冰」弱关系社交
ECCV 2022 Huake & ETH propose OSFormer, the first one-stage Transformer framework for camouflaging instance segmentation!The code is open source!...
Judging decimal points and rounding of decimal operations in Golang
[Intensive reading of the paper] iNeRF
基于单片机GSM的防火防盗系统的设计
Chapter VII
Dry goods | 10 tips for MySQL add, delete, change query performance optimization
随机推荐
BM3 将链表中的节点每k个一组翻转
MySQL数据库‘反斜杠\’ ,‘单引号‘’,‘双引号“’,‘null’无法存储
一款国外开发的高质量WordPress下载站模板主题
高效并发:Synchornized的锁优化详解
「SDOI2016」征途 题解
The difference between adding or not adding the ref keyword when a variable of reference type is used as a parameter in a method call in C#
focus on!Haitai Fangyuan joins the "Personal Information Protection Self-discipline Convention"
无状态与有状态的区别
Write a database document management tool based on WPF repeating the wheel (1)
基于RT1052 Aworks nanopb string 类型固定长度使用方式(二十七)
Implementing a Simple Framework for Managing Object Information Using Reflection
A solution to the server encountered an internal error that prevented it from fulfilling this request [easy to understand]
"The core concept of" image classification and target detection in the positive and negative samples and understanding architecture
Pytorch lstm time series prediction problem stepping on the pit "recommended collection"
[QNX Hypervisor 2.2用户手册]9.16 system
renderjs usage in uni-app
利用反射实现一个管理对象信息的简单框架
Flink_CDC construction and simple use
HTC使用官方固件作为底包制作rom卡刷包教程
面试突击69:TCP 可靠吗?为什么?