手痒就自己实现了一下简易的web服务器,由于只是简易的web服务器,所以并没有什么特别高深的技术含量。
1. TCP通信(socket)
2. IO流
3. 线程池技术
服务器架构也简单:
Request类主要是实现解析URL的功能,以获取html文件的路径。
Response类实现读取html文件并且向浏览器输出html文件内容。
Server类整合Request类和Response类,实现线程的run方法。
Test类实现线程池,同时也是服务启动类。
下图是浏览器发给服务器的内容:
下面是效果图:
1.服务器输出的日志
页面效果图:
下面贴一些关键代码:
package request; import java.io.BufferedReader; import java.io.IOException; public class Request { private String fileroute=null; private BufferedReader br=null; public Request(BufferedReader br) { this.br=br; } public void parse(){ String info=null; StringBuffer msg=new StringBuffer(); try { while((info=br.readLine())!=null && info.length()>0){//循环读取客户端的信息 msg.append(info); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } fileroute=parseFileroute(msg.toString()); } //由浏览器发给服务器内容的规律进行读取文件路径 private String parseFileroute(String requestString) { int index1, index2; index1 = requestString.indexOf(‘ ‘); if (index1 != -1) { index2 = requestString.indexOf(‘ ‘, index1 + 1); if (index2 > index1) return requestString.substring(index1 + 1, index2); } return null; } //获取html文件名 public String getFileroute(){ return fileroute; } }
package response; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; public class Response { private PrintWriter pw=null; private String fileroute=null; public Response(PrintWriter pw, String fileroute) { this.pw=pw; this.fileroute=fileroute; } public void doresponse() { File file=new File("webapp"+fileroute); // System.out.println(file.getAbsolutePath()); if(!file.exists() || !file.isFile()) //不是文件或不存在 return; FileInputStream is=null; InputStreamReader isr=null; BufferedReader br=null; try { is=new FileInputStream(file); isr=new InputStreamReader(is); br=new BufferedReader(isr); String info; StringBuffer msg=new StringBuffer(); while((info=br.readLine())!=null && info.length()>0){//循环读取html文件内容 msg.append(info); } //将文件内容输出到浏览器 pw.write(msg.toString()); pw.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ //关闭资源 try { if(br!=null) br.close(); if(isr!=null) isr.close(); if(is!=null) is.close(); } catch (IOException e) { e.printStackTrace(); } } } }
package server; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; import request.Request; import response.Response; /* * 基于TCP协议的Socket通信,实现用户登陆 * 服务器端 */ public class Server implements Runnable { private Socket socket=null; public Server(Socket socket) { this.socket=socket; } @Override public void run() { System.out.println(Thread.currentThread().getName()); //输出当前线程名字 InputStream is=null; InputStreamReader isr=null; BufferedReader br=null; OutputStream os=null; PrintWriter pw=null; //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口 try { //接收请求 进入阻塞状态 InetAddress address=socket.getInetAddress(); System.out.println("当前客户端的IP:"+address.getHostAddress()); System.out.println("当前客户端端口:" + socket.getPort()); is=socket.getInputStream(); isr=new InputStreamReader(is); br=new BufferedReader(isr); Request request = new Request(br); request.parse(); os = socket.getOutputStream(); pw = new PrintWriter(os); Response response = new Response(pw, request.getFileroute()); response.doresponse(); } catch (IOException e) { // TODO: handle exception e.printStackTrace(); } finally { //关闭资源 try { if(pw!=null) pw.close(); if(os!=null) os.close(); if(br!=null) br.close(); if(isr!=null) isr.close(); if(is!=null) is.close(); if(socket!=null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
package test; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import server.Server; public class Test { public static void main(String[] args) { ExecutorService pool=null; ServerSocket serverSocket=null; try { serverSocket=new ServerSocket(80); // 创建一个可重用固定线程数的线程池 线程数为5 pool = Executors.newFixedThreadPool(5); Socket socket=null; while(true) { socket=serverSocket.accept(); // new Thread(new Server(socket)).start(); pool.execute(new Server(socket)); } } catch (IOException e) { e.printStackTrace(); } finally { if(pool!=null) pool.shutdown(); try { if(serverSocket!=null) serverSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
一个不错的练手项目,涉及到JAVA的IO,Socket,多线程,大家都可以试着实现一下。
时间: 2024-10-13 18:18:31