zoukankan      html  css  js  c++  java
  • 阻塞式简易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

  • 相关阅读:
    css之vertical-align属性
    特殊方法,类之间的关系,分页
    内置函数lambda,sorted,filter,map,函数递归,递归实现文件的遍历,计算文件夹的大小,二分法查找
    生成器函数,推导式
    函数名,函数的闭包和迭代器
    初级简单逻辑完成BMI指数函数程序
    函数
    文件操作
    pycharmde 安装激活
    列表的join方法,类方法formkeys,删除,集合,深浅拷贝赋值,冒泡排序
  • 原文地址:https://www.cnblogs.com/yuyuj/p/4524585.html
Copyright © 2011-2022 走看看