自己动手实现HTTP协议
来源:互联网 发布:适合游戏编程的电脑 编辑:程序博客网 时间:2024/06/08 01:54
Java中的网络通信是通过Socket实现的,我们可以编写自己的SocketServer服务器接收并处理来自客户端Socket的请求。当客户端请求不是很多的时候,ServerSocket完全可以应付,但是当请求增多的时候,这种ServerSocket的模式就不那么合适了。
从JDK1.4开始,Java增加了新的io模式–nio,它在底层采用了新的处理方式,极大地提高了IO的效率。那么我们可以使用NioSocket来完成服务端,以提高处理效率。
那么,接下来我们在NioSocketServer的基础上,自己做一个简单的实现了HTTP协议的例子。
import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.util.Iterator;/** * 采用新IO方式的ServerSocket */public class NIOServer { public static void main(String[] args) throws IOException { //创建ServerSocketChannel,监听8080端口 ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.socket().bind(new InetSocketAddress(8080)); //设置为非阻塞模式 ssc.configureBlocking(false); //给ssc注册选择器 Selector selector = Selector.open(); ssc.register(selector, SelectionKey.OP_ACCEPT); //创建处理器 while (true) { //等待请求,每次等待阻塞3s,超过3s后线程继续向下运行,传入0或不传参数将一直阻塞 if (selector.select(3000) == 0) { System.out.println("等待请求超时……"); continue; } System.out.println("开始处理请求……"); Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); //启动新线程处理SelectionKey new Thread(new HttpHandler(key)).run(); //处理完成后,从待处理的SelectionKey迭代器中移除当前所使用的Key keyIterator.remove(); } } } /** * 内部类HttpHandler,负责处理监听到的请求 */ private static class HttpHandler implements Runnable { private int bufferSize = 1024; private String localCharset = "utf-8"; private SelectionKey key; private HttpHandler(SelectionKey key) { this.key = key; } private HttpHandler(int bufferSize) { this(bufferSize, null); } private HttpHandler(String localCharset) { this(-1, localCharset); } private HttpHandler(int bufferSize, String localCharset) { if (bufferSize > 0) { this.bufferSize = bufferSize; } if (localCharset != null) { this.localCharset = localCharset; } } public void handleAccept(SelectionKey key) throws IOException { SocketChannel sc = ((ServerSocketChannel) key.channel()).accept(); sc.configureBlocking(false); sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize)); } public void handleRead(SelectionKey key) throws IOException { //获取channel SocketChannel sc = (SocketChannel) key.channel(); //获取ByteBuffer并重置 ByteBuffer buffer = (ByteBuffer) key.attachment(); buffer.clear(); //没有读取到内容,关闭信道 if (sc.read(buffer) == -1) { sc.close(); } else { //将buffer转换为读状态 buffer.flip(); //将buffer中的值按localCharset格式编码后保存到receivedString String receivedString = Charset.forName(localCharset).newDecoder().decode(buffer).toString(); //控制台打印请求报文头 String[] requestMessage = receivedString.split("\r\n"); for (String s : requestMessage) { //遇到空行说明报文头已经打印完 if (s.isEmpty()) { break; } System.out.println(s); } //控制台打印首行信息 String[] firstLine = requestMessage[0].split(" "); System.out.println(); System.out.println("Method:\t" + firstLine[0]); System.out.println("URL:\t" + firstLine[1]); System.out.println("HTTP Version:\t" + firstLine[2]); System.out.println(); //返回数据给客户端 StringBuilder sb = new StringBuilder(); sb.append("HTTP/1.1 200 OK\r\n");//响应报文首行,表示请求成功 sb.append("Content-Type:text/html;charset=").append(localCharset).append("\r\n"); sb.append("\r\n");//报文头结束后需要加一个空行 sb.append("<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><title>显示报文</title></head><body>") .append("接收到的报文是:<br/>"); for (String s : requestMessage) { sb.append(s).append("<br/>"); } sb.append("</body></html>"); buffer = ByteBuffer.wrap(sb.toString().getBytes(localCharset)); sc.write(buffer); //关闭socket sc.close(); } } @Override public void run() { try { //接收到连接请求时 if (key.isAcceptable()) { handleAccept(key); } //读数据 if (key.isReadable()) { handleRead(key); } } catch (IOException e) { e.printStackTrace(); } } }}
启动这个程序,然后再浏览器输入http://127.0.0.1:8080发起请求,这是控制台和浏览器窗口都会输出这次请求的请求头以及相应的响应信息。
阅读全文
0 0
- 自己动手实现HTTP协议
- 自己动手实现HTTP协议
- 自己动手实现http协议(看透spring mvc笔记)
- 自己动手学TCP/IP–http协议(http报文格式)
- 自己动手学TCP/IP–http协议(http报文头)
- 自己动手学TCP/IP–http协议(http报文格式)
- 自己动手学TCP/IP–http协议(http报文格式)
- 自己动手利用Socket 实现HTTP与HTTPS
- HTTP协议(下):HTTP协议实现通信
- http协议上传实现
- vb实现http协议
- vb实现http协议
- http协议实现上传
- telnet 实现HTTP协议
- HTTP传输协议实现
- C++ 实现http 协议
- http协议上传实现
- telnet 实现HTTP协议
- 今天的心情还是不错的 找到了一些好的方法
- Python2.7 + selenium3.0配置
- 嵌入式安装telnet
- react native 实现ListView的局部更新
- 【MySQL】为什么不要问我DB极限QPS/TPS
- 自己动手实现HTTP协议
- GYM100702 D
- PHP常量
- POJ 1294 Not Too Convex Hull 笔记
- Can‘t connet to repository from configured remote.
- 170611 逆向-gctf的debug的writeup
- C#编写简单窗体计算器
- django+gunicorn+nginx, WebSocket无法正常连接
- 好用用的linux 监控命令