• 说明

        需要理解阻塞和非阻塞的区别,特别要注意非阻塞和异步不是一个概念,这个很容易弄错。云盘里面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. burpsuite的使用(三)

    send to repeater 手动提交,注入. 将post请求改成get请求 直接就可以看到页面 生成csrf POC代码 点击在浏览器中测试,copy 拿到浏览器里访问 或者拷贝出来 保存到文本 ...

  2. 算法之LOWB三人组之冒泡排序

    排序 冒泡排序(Bubble Sort)时间复杂度为O(n^2) 列表每两个相邻的数,如果前面比后面大,则交换这两个数 一趟排序完成后,则无序区减少一个数,有序区增加一个数. def bubble_s ...

  3. Vue之数据监听存在的问题

    Vue之数据监听 当数据监听的是列表时,数据发生改变,不会被监听到. // 用$set修改数组中的数组能够被监听 // app.$set(this.hobby, 0, "爱你哦") ...

  4. NYOJ-1058 DFS部分求和

    原题链接 本题思路:暴力深搜,具体见代码. #include <iostream> #include <stack> using namespace std; + ; int ...

  5. Linux系统(Centos)下安装nodejs并配置环境

    总结Centos下安装nodejs并配置环境,记录成功安装的方法.推荐的安装方法是利用已编译的二进制文件安装,不推荐使用源码的形式安装,一是源码安装比较麻烦,二是需要自行下载编译浪费时间. 1.安装n ...

  6. sql case 与 sum

    <select id="selectTotal" resultType="java.util.Map" parameterType="java. ...

  7. js replaceAll全部替换

    js不支持replaceAll,可以用函数new RegExp('要替换的内容','g')代替, 代码: str.replace(new RegExp('要替换的内容','g'),"替换内容 ...

  8. [leetcode]694. Number of Distinct Islands你究竟有几个异小岛?

    Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...

  9. Number & Maths类

    Java Number & Math 类 一般地,当需要使用数字的时候,我们通常使用内置数据类型,如:byte.int.long.double 等. 实例 int a = 5000;float ...

  10. Js或 Activex 控件调用打印预览等操作

    <input value="打印" type="button" onclick="javascript:window.print()" ...