• 说明

        使用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. JMeter3.0(三十八)图形化HTML报告中文乱码问题处理(转载)

    转载自 http://www.cnblogs.com/yangxia-test 由于个人在JMeter 3.0的实际应用中,脚本中的Test Plan/Sampler等元件命名都没有使用中文,所以在之 ...

  2. as3.0橡皮擦功能

    //主容器 var main:Sprite = new Sprite(); main.mouseEnabled = false; addChild(main) //临时容器(所有操作都将先画在临时容器 ...

  3. CodeForces - 873B Balanced Substring(思维)

    inputstandard input outputstandard output You are given a string s consisting only of characters 0 a ...

  4. [剑指Offer]48-最长不含重复字符的子字符串(递归思想,循环实现)

    题意 如题,字符串只含a-z,输出该子串长度.例:"arabcacfr",输出4. 解题思路 递归思想 计f(i)为以第i个字符结尾的最长不含重复字符的子串长度. 状态转移:计d为 ...

  5. iOS版本设置

    Base SDK指的是当前编译所用的SDK 版本: iOS Deployment Target指的是,编译后的 app 可在 终端的哪个 版本上运行. 设置方法: 点击xcode工程左侧项目名称-&g ...

  6. 《基于Nginx的中间件架构》学习笔记---1.环境配置

    一.环境调试确认 (四项确认) 1.确认系统网络 ping www.baidu.com 2.确认yum可用 yum list|grep gcc 3.确认关闭iptables规则 iptables -L ...

  7. 【php 之获得当前日期以及比较日期大小】

    首先看一个例子: $currentTime = date('Y-m-d H:i'); // 获得当前时间 $timer = $searchDated . ' ' . $results['ctrip'] ...

  8. swift4.2 打印devicetoken

    import UIKit import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicati ...

  9. vs的【warning C4996:'fopen': This function or variable may be unsafe】解决方案

    编译警告:warning C4996 与 Security Enhancements in the CRT 将过去的工程用VS2005打开的时候.你有可能会遇到一大堆的警告:warning C4996 ...

  10. Linux netstat

    一.简介   二.语法   三.实例 1)查看TCP连接数 netstat -n | awk '/^tcp/ {++S[$NF]} END {for (a in S) print a, S[a]}'