zoukankan      html  css  js  c++  java
  • 简易非阻塞http服务器

    • 说明

            需要理解阻塞和非阻塞的区别,特别要注意非阻塞和异步不是一个概念,这个很容易弄错。云盘里面netty的书会讲这几个方面的区别,nodejs深入浅出关于异步编程章节里面        也会讲到网络通信底层的知识,可以看看下面文章:

            http://blog.csdn.net/hguisu/article/details/7453390

            http://www.cnblogs.com/dolphin0520/p/3916526.html


    •  Handler接口类
    1 package study.socket.tcp.nonblock.simpleserver;
    2 
    3 import java.io.IOException;
    4 import java.nio.channels.SelectionKey;
    5 
    6 public interface Handler {
    7 
    8     public void handle(SelectionKey selectionKey) throws IOException;
    9 }
    View Code

    • 请求连接Handler实现类
     1 package study.socket.tcp.nonblock.simpleserver;
     2 
     3 import java.io.IOException;
     4 import java.nio.channels.SelectionKey;
     5 import java.nio.channels.ServerSocketChannel;
     6 import java.nio.channels.SocketChannel;
     7 
     8 public class AcceptHandler implements Handler{
     9 
    10     @Override
    11     public void handle(SelectionKey selectionKey) throws IOException {
    12         System.out.println("开始处理连接请求");
    13         try {
    14             Thread.sleep(60000);
    15         } catch (InterruptedException e) {
    16             e.printStackTrace();
    17         }
    18         //得到事件发生的通道
    19         ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
    20         //获得和客户端连接的通道
    21         SocketChannel socketChannel = ssc.accept();
    22         //设置曾非阻塞模式
    23         socketChannel.configureBlocking(false);
    24         //在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读权限
    25         socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ, new RequestHandler());
    26         System.out.println("连接成功");
    27     }
    28 
    29 }
    View Code

    •  请求处理Handler实现类
     1 package study.socket.tcp.nonblock.simpleserver;
     2 
     3 import java.io.FileInputStream;
     4 import java.io.IOException;
     5 import java.nio.ByteBuffer;
     6 import java.nio.CharBuffer;
     7 import java.nio.channels.FileChannel;
     8 import java.nio.channels.SelectionKey;
     9 import java.nio.channels.SocketChannel;
    10 import java.nio.charset.Charset;
    11 import java.nio.charset.CharsetDecoder;
    12 
    13 public class RequestHandler implements Handler{
    14 
    15     @Override
    16     public void handle(SelectionKey selectionKey) throws IOException {
    17         FileInputStream fis = null;
    18         SocketChannel socketChannel = null;
    19         try {
    20             socketChannel = (SocketChannel) selectionKey.channel();
    21             ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    22             socketChannel.read(byteBuffer);
    23             byte[] data = byteBuffer.array();
    24             String msg = new String(data);
    25             System.out.println("接收客户端的消息:" + msg);
    26             byteBuffer.flip();
    27             String request = decode(byteBuffer);
    28             System.out.println("客户端请求消息:" + request);
    29             //生成http响应消息
    30             StringBuffer sb = new StringBuffer("HTTP/1.1 200 OK
    ");
    31             sb.append("Content-Type:text/html
    
    ");
    32             //发送http响应第一行和响应头
    33             socketChannel.write(encode(sb.toString()));
    34             
    35             //获取http请求的第一行
    36             String firstLineOfRequst = request.substring(0, request.indexOf("
    "));
    37             String filePath = SimpleHttpServer.class.getResource("/").getPath();
    38             System.out.println("路径:" + filePath);
    39             System.out.println("测试");
    40             if(firstLineOfRequst.indexOf("login.html") != -1) {
    41                 fis = new FileInputStream(filePath + "study/socket/block/httpserver/login.html");
    42             }else {
    43                 fis = new FileInputStream(filePath + "study/socket/block/httpserver/hello.html");
    44             } 
    45             FileChannel fc = fis.getChannel();
    46             fc.transferTo(0, fc.size(), socketChannel);
    47         } catch(Exception e){
    48             e.printStackTrace();
    49         }finally {
    50             if(fis != null) {
    51                 try {
    52                     fis.close();
    53                 } catch (IOException e1) {
    54                     e1.printStackTrace();
    55                 }
    56             }
    57             if(socketChannel != null) {
    58                 try {
    59                     socketChannel.close();
    60                 } catch (IOException e1) {
    61                     e1.printStackTrace();
    62                 }
    63             }
    64         }
    65     }
    66     //编码
    67     private String decode(ByteBuffer bb) throws Exception{
    68         Charset charset  =  Charset.forName("utf-8");
    69         CharsetDecoder decoder  =  charset.newDecoder();
    70         CharBuffer charBuffer  =  decoder.decode(bb);
    71         System.out.println( " charBuffer= "   +  charBuffer);
    72         System.out.println(charBuffer.toString());
    73         System.out.println("编码");
    74         return  charBuffer.toString();
    75     }
    76     //解码
    77     private ByteBuffer encode(String str) {
    78         System.out.println("解码");
    79         return ByteBuffer.wrap(str.getBytes());
    80     }
    81 }
    View Code

    •  nio编写的服务端类
     1 package study.socket.tcp.nonblock.simpleserver;
     2 
     3 import java.io.IOException;
     4 import java.net.InetSocketAddress;
     5 import java.nio.channels.SelectionKey;
     6 import java.nio.channels.Selector;
     7 import java.nio.channels.ServerSocketChannel;
     8 import java.util.Iterator;
     9 
    10 /**
    11  * 非阻塞式简易http服务器
    12  * @author yj
    13  *
    14  */
    15 public class SimpleHttpServer {
    16 
    17     private int port = 8080;
    18     private Selector selector;
    19     
    20     public void initServer() throws IOException{
    21         //打开服务器套接字通道
    22         ServerSocketChannel ssc = ServerSocketChannel.open();
    23         //将服务端套接字通道连接方式改为非阻塞模式
    24         ssc.configureBlocking(false);
    25         //绑定端口
    26         ssc.socket().bind(new InetSocketAddress(port));
    27         //打开通道选择器
    28         this.selector = Selector.open();
    29         //将服务器套接字通道的OP_ACCEPT事件注册到通道选择器上
    30         ssc.register(selector, SelectionKey.OP_ACCEPT, new AcceptHandler());
    31     }
    32     
    33     public void service() throws IOException{
    34         while(true) {
    35             int n = selector.select();
    36             System.out.println("开始处理请求");
    37             if(n == 0) continue;
    38             //获取通道选择器事件
    39             Iterator<SelectionKey> itr = this.selector.selectedKeys().iterator();
    40             while(itr.hasNext()) {
    41                 SelectionKey sk = null;
    42                 try {
    43                     sk = itr.next();
    44                     itr.remove();
    45                     Handler handler = (Handler) sk.attachment();
    46                     handler.handle(sk);
    47                 } catch(Exception e) {
    48                     e.printStackTrace();
    49                 }
    50             }
    51             System.out.println("请求处理完成");
    52         }
    53     }
    54     
    55     public static void main(String[] args) {
    56         try {
    57             SimpleHttpServer2 nioServer = new SimpleHttpServer2();
    58             nioServer.initServer();
    59             nioServer.service();
    60         } catch (Exception e) {
    61             e.printStackTrace();
    62         }
    63     }
    64 }
    View Code

    • html文件

            html文件使用《简易阻塞http服务器》中的两个html文件,注意文件目录与上面类文件所在目录一致。


    • 测试

            启动main方法,浏览器输入:http://ip:port/或http://ip:port/hello.html访问hello.html,输入http://ip:port/login.html访问login.html.


    • 云盘资料

           http://yunpan.cn/cwJGv4vUm9kTf  访问密码 a74b     里面包含了io.socket和nio.socket的一些简单代码,还有上面说的netty的书。

  • 相关阅读:
    sql -- 获取商品分类的最新销售情况
    sql -- 获取连续签到的用户列表
    sql -- 利用order by 排名作弊
    sql -- update表子查询、多条件判断case when
    sql-- 找到重复数据并删除、有重复数据不插入或更新的处理方法
    sql--自链接(推荐人)
    sql--测试商品的重要度,是否需要及时补货
    sql面试题
    TCP/IP 3次握手
    REST和SOAP
  • 原文地址:https://www.cnblogs.com/yuyuj/p/4524651.html
Copyright © 2011-2022 走看看