阻塞式简易http服务器

  • 说明

        使用java.net包的ServerSocket也是阻塞的,所以下面的实例把ServerSocketChannel换成ServerSocket效果一样。


  •  后台代码
  1 package study.socket.tcp.block.httpserver;
  2 
  3 import java.io.FileInputStream;
  4 import java.io.IOException;
  5 import java.net.InetSocketAddress;
  6 import java.net.Socket;
  7 import java.nio.ByteBuffer;
  8 import java.nio.CharBuffer;
  9 import java.nio.channels.FileChannel;
 10 import java.nio.channels.ServerSocketChannel;
 11 import java.nio.channels.SocketChannel;
 12 import java.nio.charset.Charset;
 13 import java.nio.charset.CharsetDecoder;
 14 import java.util.concurrent.ExecutorService;
 15 import java.util.concurrent.Executors;
 16 
 17 /**
 18  * 阻塞式简易http服务器
 19  * @author yj
 20  *
 21  */
 22 public class SimpleHttpServer {
 23 
 24     private int port = 8080;
 25     private ServerSocketChannel serverSocketChannel = null;
 26     private ExecutorService executorService;
 27     private static final int POOL_MULTIPE = 4;
 28     
 29     public SimpleHttpServer() throws Exception {
 30         executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_MULTIPE);
 31         serverSocketChannel = ServerSocketChannel.open();
 32         serverSocketChannel.socket().setReuseAddress(true);
 33         serverSocketChannel.socket().bind(new InetSocketAddress(port));
 34         System.out.println("服务器启动");
 35     }
 36     
 37     public void service() {
 38         while(true) {
 39             System.out.println("服务器接收到客户端请求");
 40             SocketChannel socketChannel = null;
 41             try {
 42                 socketChannel = serverSocketChannel.accept();
 43             } catch (IOException e) {
 44                 e.printStackTrace();
 45             }
 46             executorService.execute(new Handler(socketChannel));
 47             System.out.println("服务端处理完客户端请求");
 48         }
 49     }
 50     
 51     private class Handler implements Runnable {
 52 
 53         private SocketChannel socketChannel;
 54         
 55         public Handler(SocketChannel socketChannel) {
 56             this.socketChannel = socketChannel;
 57         }
 58         
 59         @Override
 60         public void run() {
 61             handler();
 62         }
 63         
 64         private void handler() {
 65             FileInputStream fis = null;
 66             try{
 67                 new Thread().sleep(60000);
 68                 Socket socket = socketChannel.socket();
 69                 System.out.println("接受到客户连接来自:" + socket.getInetAddress() + ":" + socket.getPort());
 70                 ByteBuffer bb = ByteBuffer.allocate(1024);
 71                 socketChannel.read(bb);
 72                 bb.flip();
 73                 String request = decode(bb);
 74                 System.out.println("客户端请求消息:" + request);
 75                 //生成http响应消息
 76                 StringBuffer sb = new StringBuffer("HTTP/1.1 200 OK
");
 77                 sb.append("Content-Type:text/html

");
 78                 //发送http响应第一行和响应头
 79                 socketChannel.write(encode(sb.toString()));
 80                 
 81                 //获取http请求的第一行
 82                 String firstLineOfRequst = request.substring(0, request.indexOf("
"));
 83                 String filePath = SimpleHttpServer.class.getResource("/").getPath();
 84                 System.out.println("路径:" + filePath);
 85                 System.out.println("测试");
 86                 if(firstLineOfRequst.indexOf("login.html") != -1) {
 87                     fis = new FileInputStream(filePath + "study/socket/block/httpserver/login.html");
 88                 }else {
 89                     fis = new FileInputStream(filePath + "study/socket/block/httpserver/hello.html");
 90                 } 
 91                 FileChannel fc = fis.getChannel();
 92                 fc.transferTo(0, fc.size(), socketChannel);
 93             }catch(Exception e){
 94                 e.printStackTrace();
 95             }finally {
 96                 try {
 97                     if(fis != null) {
 98                         fis.close();
 99                     }
100                     if(socketChannel != null) {
101                         socketChannel.close();
102                     }
103                 } catch (IOException e) {
104                     e.printStackTrace();
105                 }
106             }
107         }
108         
109         private String decode(ByteBuffer bb) throws Exception{
110             Charset charset  =  Charset.forName("utf-8");
111             CharsetDecoder decoder  =  charset.newDecoder();
112             CharBuffer charBuffer  =  decoder.decode(bb);
113             System.out.println( " charBuffer= "   +  charBuffer);
114             System.out.println(charBuffer.toString());
115             System.out.println("编码");
116             return  charBuffer.toString();
117         }
118         
119         private ByteBuffer encode(String str) {
120             System.out.println("解码");
121             return ByteBuffer.wrap(str.getBytes());
122         }
123         
124     }
125     
126     public static void main(String[] args) {
127         try {
128             new SimpleHttpServer().service();
129         } catch (Exception e) {
130             e.printStackTrace();
131         }
132     }
133 }
View Code

  • hello.html文件

        html文件放在类的同级目录下,如果放其他目录下,上面后台代码需要改变取html文件路径。

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="UTF-8">
 5 <title>Insert title here</title>
 6 </head>
 7 <body>
 8     <h1>hello</h1>
 9 </body>
10 </html>
View Code

  • login.html文件

        html文件放在类的同级目录下,如果放其他目录下,上面后台代码需要改变取html文件路径。

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="UTF-8">
 5 <title>Insert title here</title>
 6 </head>
 7 <body>
 8     <h1>login</h1>
 9 </body>
10 </html>
View Code
  • 测试

       浏览器中输入:http://ip:port/或http://ip:port/hello.html访问hello.html,输入:http://ip:port/login.html访问login.html

原文地址:https://www.cnblogs.com/yuyuj/p/4524585.html