• 说明

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

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

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


  • Handler接口类
 package study.socket.tcp.nonblock.simpleserver;

 import java.io.IOException;
import java.nio.channels.SelectionKey; public interface Handler { public void handle(SelectionKey selectionKey) throws IOException;
}

  • 请求连接Handler实现类
 package study.socket.tcp.nonblock.simpleserver;

 import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel; public class AcceptHandler implements Handler{ @Override
public void handle(SelectionKey selectionKey) throws IOException {
System.out.println("开始处理连接请求");
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//得到事件发生的通道
ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
//获得和客户端连接的通道
SocketChannel socketChannel = ssc.accept();
//设置曾非阻塞模式
socketChannel.configureBlocking(false);
//在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读权限
socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ, new RequestHandler());
System.out.println("连接成功");
} }

  •  请求处理Handler实现类
 package study.socket.tcp.nonblock.simpleserver;

 import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder; public class RequestHandler implements Handler{ @Override
public void handle(SelectionKey selectionKey) throws IOException {
FileInputStream fis = null;
SocketChannel socketChannel = null;
try {
socketChannel = (SocketChannel) selectionKey.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
socketChannel.read(byteBuffer);
byte[] data = byteBuffer.array();
String msg = new String(data);
System.out.println("接收客户端的消息:" + msg);
byteBuffer.flip();
String request = decode(byteBuffer);
System.out.println("客户端请求消息:" + request);
//生成http响应消息
StringBuffer sb = new StringBuffer("HTTP/1.1 200 OK\r\n");
sb.append("Content-Type:text/html\r\n\r\n");
//发送http响应第一行和响应头
socketChannel.write(encode(sb.toString())); //获取http请求的第一行
String firstLineOfRequst = request.substring(0, request.indexOf("\r\n"));
String filePath = SimpleHttpServer.class.getResource("/").getPath();
System.out.println("路径:" + filePath);
System.out.println("测试");
if(firstLineOfRequst.indexOf("login.html") != -1) {
fis = new FileInputStream(filePath + "study/socket/block/httpserver/login.html");
}else {
fis = new FileInputStream(filePath + "study/socket/block/httpserver/hello.html");
}
FileChannel fc = fis.getChannel();
fc.transferTo(0, fc.size(), socketChannel);
} catch(Exception e){
e.printStackTrace();
}finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if(socketChannel != null) {
try {
socketChannel.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
//编码
private String decode(ByteBuffer bb) throws Exception{
Charset charset = Charset.forName("utf-8");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(bb);
System.out.println( " charBuffer= " + charBuffer);
System.out.println(charBuffer.toString());
System.out.println("编码");
return charBuffer.toString();
}
//解码
private ByteBuffer encode(String str) {
System.out.println("解码");
return ByteBuffer.wrap(str.getBytes());
}
}

  •  nio编写的服务端类
 package study.socket.tcp.nonblock.simpleserver;

 import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator; /**
* 非阻塞式简易http服务器
* @author yj
*
*/
public class SimpleHttpServer { private int port = 8080;
private Selector selector; public void initServer() throws IOException{
//打开服务器套接字通道
ServerSocketChannel ssc = ServerSocketChannel.open();
//将服务端套接字通道连接方式改为非阻塞模式
ssc.configureBlocking(false);
//绑定端口
ssc.socket().bind(new InetSocketAddress(port));
//打开通道选择器
this.selector = Selector.open();
//将服务器套接字通道的OP_ACCEPT事件注册到通道选择器上
ssc.register(selector, SelectionKey.OP_ACCEPT, new AcceptHandler());
} public void service() throws IOException{
while(true) {
int n = selector.select();
System.out.println("开始处理请求");
if(n == 0) continue;
//获取通道选择器事件
Iterator<SelectionKey> itr = this.selector.selectedKeys().iterator();
while(itr.hasNext()) {
SelectionKey sk = null;
try {
sk = itr.next();
itr.remove();
Handler handler = (Handler) sk.attachment();
handler.handle(sk);
} catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("请求处理完成");
}
} public static void main(String[] args) {
try {
SimpleHttpServer2 nioServer = new SimpleHttpServer2();
nioServer.initServer();
nioServer.service();
} catch (Exception e) {
e.printStackTrace();
}
}
}

  • 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的书。

简易非阻塞http服务器的更多相关文章

  1. Java NIO 非阻塞Socket服务器构建

    推荐阅读IBM developerWorks中NIO的入门教程,尤其是对块I/O和流I/O不太清楚的开发者. 说到socket服务器,第一反应是java.net.Socket这个类.事实上在并发和响应 ...

  2. 非阻塞tcp服务器与阻塞的tcp服务器对比

    一般的tcp服务器(阻塞)是使用的如下 [erlang] gen_tcp传输文件原型 http://www.cnblogs.com/bluefrog/archive/2012/09/10/267904 ...

  3. Tornado之自定义异步非阻塞的服务器和客户端

    一.自定义的异步非阻塞的客户端 #!/usr/bin/env python # -*- coding: utf8 -*- # __Author: "Skiler Hao" # da ...

  4. PHP异步非阻塞fsockopen(本地可以非阻塞请求,服务器就一直执行异步的不成功) (未解决)

    index.php /** * php异步请求 * * @param $host string 主机地址 * @param $path string 路径 * @param $param array ...

  5. 高性能非阻塞 Web 服务器 Undertow

    Undertow 简介 Undertow是一个用java编写的.灵活的.高性能的Web服务器,提供基于NIO的阻塞和非阻塞API. Undertow的架构是组合式的,可以通过组合各种小型的目的单一的处 ...

  6. 2017年5月12日15:10:46 rabbitmq不支持非阻塞调用服务器

    就像昨天碰到的问题描述一样,问题不是出在消费者上而是在生产者发送消息出现没有得到返回值时消息通道被挂起,rabbitmq发送的消息是阻塞调用即当发生阻塞时,继续发送的消息都堆在后面.在网上看到有两个方 ...

  7. Android NIO(Noblocking I/O非阻塞I/O)小结

    参考:http://www.cnblogs.com/cpcpc/archive/2011/06/27/2123009.html 对于Android的网络通讯性能的提高,我们可以使用Java上高性能的N ...

  8. JAVA 中BIO,NIO,AIO的理解以及 同步 异步 阻塞 非阻塞

    在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步 ...

  9. 关于同步,异步,阻塞,非阻塞,IOCP/epoll,select/poll,AIO ,NIO ,BIO的总结

    相关资料 IO基本概念 Linux环境 同步异步阻塞非阻塞 同步与异步 阻塞与非阻塞 IO模型Reference Link 阻塞IO模型 非阻塞IO模型 IO复用模型 信号驱动异步IO模型 异步IO模 ...

随机推荐

  1. Java LinkedList

    LinkedList是基于双向链表实现的,先看构造方法和方法 Constructor Summary Constructors Constructor Description LinkedList() ...

  2. python3获得命令行输入的参数

    外部直接执行python文件时,我们有时需要获得命令行的参数   获得命令行参数的两种方式   1.通过sys.argv sys.argv:获得一个参数列表,第一个值为文件名本身,通过sys.argv ...

  3. BP神经网络学习

    人工神经元模型     S型函数(Sigmoid) 双极S型函数 神经网络可以分为哪些? 按照连接方式,可以分为:前向神经网络 vs. 反馈(递归)神经网络 按照学习方式,可以分为:有导师学习神经网络 ...

  4. HDU-1004.Let the ballon Rise(STL-map)

    2019-02-28-08:56:03 初次做本题是用字符串硬钢,最近校队训练时又遇到才知道用map是真的舒服.需要注意的是map的用法. clear : 清除map中的所有元素,map.clear( ...

  5. oracle中获取当前整点和上一个小时整点,日期类型

    select to_date(to_char(sysdate,'yyyy-mm-dd hh'),'yyyy-mm-dd hh:mi:ss') from dual;select to_date(to_c ...

  6. 大数据入门推荐 - 数据之巅 大数据革命,历史、现实与未来等五本PDF

    扫码时备注或说明中留下邮箱付款后如未回复请至https://shop135452397.taobao.com/联系店主

  7. ECMAScript2017之async function

    An async function can contain an await expression that pauses the execution of the async function an ...

  8. 以太坊博弈游戏 -- FOMO3D,讽刺人性

    以下资料收录自各个博客,下面给出链接. 总的来说,这是基于以太坊的“菠菜”游戏,大资金盘,亏多盈少,大家看看就好. 官网地址:http://exitscam.me/play 出现 7月16日,当时这个 ...

  9. TZOJ 2725 See you~(二维树状数组单点更新区间查询)

    描述 Now I am leaving hust acm. In the past two and half years, I learned so many knowledge about Algo ...

  10. 有关defer和async的区别

    关于async.defer功能及异同的介绍 async属性会让js并行加载,并在js加载完成后立即执行,也就是说执行顺序由加载速度定,而不是html中的先后顺序 defer属性js同样会并行加载,而执 ...