• 说明

        需要理解阻塞和非阻塞的区别,特别要注意非阻塞和异步不是一个概念,这个很容易弄错。云盘里面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. SSL、TLS中间人攻击

    生成私钥 生成一个ca.key私钥签名 然后用私钥生成一个伪造证书服务器的根证书 生成一个伪造证书服务器的根证书ca.crt 在攻击主机启动路由转发功能 或者echo 1 > /proc/sys ...

  2. python找包的路径(找不到自定义包的问题解决)

    问题:工程下自定义的包,python在执行时经常找不到包   python找包的路径:python安装路径下的lib包和PYTHONPATH下的包     可以使用[sys.path]打印出pytho ...

  3. MongoDB之Array Object的特殊操作

    相比关系型数据库,Array[1,2,3,4,5]和Object{'name':'Wjs'}是MongoDB比较特殊的类型 db.Wjs.insert({"name":" ...

  4. Python+Selenium学习--操作测试对象

    场景 前面已经讲解了如果定位对象,定位之后需要对这个对象进行操作.是鼠标点击还是键盘输入,取决于我们定位的对象缩支持的操作. webdriver中比较常用的操作元素的方法有下面几个: clear    ...

  5. js改变表单的内容样式

    一.改变单个样式    var obj = document.getElementById("id");   obj.style.cssText = " display: ...

  6. UVa 10054 The Necklace(无向图欧拉回路)

    My little sister had a beautiful necklace made of colorful beads. Two successive beads in the neckla ...

  7. Django import相关

    from django.shortcuts import render,redirect from django.contrib.auth import authenticate,logout,log ...

  8. Intellij创建简单Springboot项目

    Intellij创建简单Springboot项目 第一步:选择创建新项目——file-new-project 第二步:选择项目类型——Spring Initializr-next 第三步:输入项目信息 ...

  9. ubuntu下nginx的常用操作

    1.安装不多说了,我是使用apt-get进行安装的,直接键入 apt-get install nginx 2.启动nginx. 首先找到nginx的主运行程序(相当于windows下的nginx.ex ...

  10. 使用IntelliJ IDEA 搭建 spring mvc开发环境

    填好GroupId.ArtifactId,一路Next创建工程,在main 目录创建 java文件夹并转换为Sources Root,创建好工程目录结构如下: 配置工程 配置 pom.xml,引入相关 ...