• 说明

        使用java.net包的ServerSocket也是阻塞的,所以下面的实例把ServerSocketChannel换成ServerSocket效果一样。


  • 后台代码
 package study.socket.tcp.block.httpserver;

 import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* 阻塞式简易http服务器
* @author yj
*
*/
public class SimpleHttpServer { private int port = 8080;
private ServerSocketChannel serverSocketChannel = null;
private ExecutorService executorService;
private static final int POOL_MULTIPE = 4; public SimpleHttpServer() throws Exception {
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_MULTIPE);
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().setReuseAddress(true);
serverSocketChannel.socket().bind(new InetSocketAddress(port));
System.out.println("服务器启动");
} public void service() {
while(true) {
System.out.println("服务器接收到客户端请求");
SocketChannel socketChannel = null;
try {
socketChannel = serverSocketChannel.accept();
} catch (IOException e) {
e.printStackTrace();
}
executorService.execute(new Handler(socketChannel));
System.out.println("服务端处理完客户端请求");
}
} private class Handler implements Runnable { private SocketChannel socketChannel; public Handler(SocketChannel socketChannel) {
this.socketChannel = socketChannel;
} @Override
public void run() {
handler();
} private void handler() {
FileInputStream fis = null;
try{
new Thread().sleep(60000);
Socket socket = socketChannel.socket();
System.out.println("接受到客户连接来自:" + socket.getInetAddress() + ":" + socket.getPort());
ByteBuffer bb = ByteBuffer.allocate(1024);
socketChannel.read(bb);
bb.flip();
String request = decode(bb);
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 {
try {
if(fis != null) {
fis.close();
}
if(socketChannel != null) {
socketChannel.close();
}
} catch (IOException e) {
e.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());
} } public static void main(String[] args) {
try {
new SimpleHttpServer().service();
} catch (Exception e) {
e.printStackTrace();
}
}
}

  • hello.html文件

        html文件放在类的同级目录下,如果放其他目录下,上面后台代码需要改变取html文件路径。

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>hello</h1>
</body>
</html>

  • login.html文件

        html文件放在类的同级目录下,如果放其他目录下,上面后台代码需要改变取html文件路径。

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>login</h1>
</body>
</html>
  • 测试

浏览器中输入:http://ip:port/或http://ip:port/hello.html访问hello.html,输入:http://ip:port/login.html访问login.html

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

  1. PHP解决抢购、秒杀、抢楼、抽奖等阻塞式高并发库存防控超量的思路方法

    如今在电商行业里,秒杀抢购活动已经是商家常用促销手段.但是库存数量有限,而同时下单人数超过了库存量,就会导致商品超卖甚至库存变负数的问题. 又比如:抢购火车票.论坛抢楼.抽奖乃至爆红微博评论等也会引发 ...

  2. 阻塞式和非阻塞式IO

    有很多人把阻塞认为是同步,把非阻塞认为是异步:个人认为这样是不准确的,当然从思想上可以这样类比,但方式是完全不同的,下面说说在JAVA里面阻塞IO和非阻塞IO的区别 在JDK1.4中引入了一个NIO的 ...

  3. Java IO(3)非阻塞式输入输出(NIO)

    在上篇<Java IO(2)阻塞式输入输出(BIO)>的末尾谈到了什么是阻塞式输入输出,通过Socket编程对其有了大致了解.现在再重新回顾梳理一下,对于只有一个“客户端”和一个“服务器端 ...

  4. python 简单搭建非阻塞式单进程,select模式,epoll模式服务

    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 可以看我的上篇文章 <python 简单搭建阻塞式单进程,多进程, ...

  5. 非阻塞式I/O

    套接字的默认状态是阻塞的.这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待相应的操作完成.可能阻塞的套接字调用可分为以下4类 (1)输入操作,包括read,readv,recv ...

  6. 4.NIO的非阻塞式网络通信

    /*阻塞 和 非阻塞 是对于 网络通信而言的*/ /*原先IO通信在进行一些读写操作 或者 等待 客户机连接 这种,是阻塞的,必须要等到有数据被处理,当前线程才被释放*/ /*NIO 通信 是将这个阻 ...

  7. Linux NIO 系列(02) 阻塞式 IO

    目录 一.环境准备 1.1 代码演示 二.Socket 是什么 2.1 socket 套接字 2.2 套接字描述符 2.3 文件描述符和文件指针的区别 三.基本的 SOCKET 接口函数 3.1 so ...

  8. node--非阻塞式I/O,单线程,异步,事件驱动

    1.单线程 不同于其他的后盾语言,node是单线程的,大大节约服务器开支 node不为每个客户创建一个新的线程,仅使用一个线程.通过非阻塞I/O以及 事件驱动机制,使其宏观上看是并发的,可以处理高并发 ...

  9. Node:使用express搭建一个简易的服务器

    ①安装node环境 在node.js官网下载LTS长期支持版本,然后傻瓜式安装 ②查看是否安装成功 打开cmd终端,输入node -v 有版本号,则安装成功.再输入npm -v 有版本号,则npm也安 ...

随机推荐

  1. Solr的搭建

    Solr6.6.0下载地址 http://www.apache.org/dyn/closer.lua/lucene/solr/ 安装JRE 需要Java Runtime Environment(JRE ...

  2. windows 下 wamp php单元测试工具PHPUnit的安装

    phpunit下载网站 http://www.phpunit.cn/ 一.安装PHPUnit 1.选择版本 我用的是php版本是5.6.25 所以我选择的是PHPUnit 5.7 2.安装过程 为 P ...

  3. VS2013 error C2556: “const int &Array<int>::operator [](int)”: 重载函数与“int &Array<int>::operator [](int)”只是在返回类型上不同

    1,VS2013 错误 1 error C2556: “const int &Array<int>::operator [](int)”: 重载函数与“int &Array ...

  4. Shell教程 之函数

    1.函数定义 shell中函数的定义格式如下: [ function ] funname [()] { action; [return int;] } 说明: 可以带function fun() 定义 ...

  5. chrome谷歌浏览器常用快捷键搜集整理

    搜集了下面比较实用的快捷键,部分不好操作的组合键就不写了:Ctrl+N:打开新窗口. Ctrl+T:打开新标签页.Ctrl+W:关闭当前标签Alt+F4:关闭chrome浏览器Ctrl+Tab:切换到 ...

  6. day 31 表单标签,CSS

    一. HTML表单标签 HTML表单用于搜集不同类型的用户输入,然后把数据提交给服务器处理. 常用的表单标签: 标签 作用 form 所有表单标签的根标签 input 输入标签,包括单行输入框.密码框 ...

  7. POI依据类型设置导出格式

    //设置Bigdecimal数据导出时以数值形式输出 CellStyle decimalStyle = workbook.createCellStyle(); DataFormat decimalDf ...

  8. Exploring the world of Android :: Part 1

    This blog is accidentally find out, it tells the story of one of our friends about the exploration o ...

  9. vue 自定义组件directives

    自定义指令:以v开头,如:v-mybind. 代码示例: <input v-mybind /> directives:{ mybind:{ bind:function (el) { el. ...

  10. mysql 查看mysql相关信息

    登入数据库的时候: select @@version; select version(); 复制代码 mysql> select @@version; +-----------+ | @@ver ...