java socket 实现http_Java Socket实现http协议

该博客介绍了如何使用Java的NIO(非阻塞I/O)通过Socket实现一个简单的HTTP服务器。内容涵盖HTTP协议的基本结构,包括请求报文和响应报文,并提供了具体的Java代码实现,用于接收和响应客户端的HTTP请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HTTP协议报文结构

HTTP 协议是应用层协议,HTTP协议报文分为请求报文和响应报文两种类型,两者都包含三部分:首行、头部、主体。

HTTP 请求报文

请求行:GET / HTTP/1.1

表示请求的方法(请求类型)、路径、协议版本

请求头:Connection: keep-alive

请求体:GET的请求体为空

HTTP 响应报文

响应行:HTTP/1.1 200

响应头:content-type: text/html; charset=utf-8

响应体:主体内容

Socket实现HTTP协议:

package it.yus.socket;

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;

import java.util.concurrent.Executor;

import java.util.concurrent.LinkedBlockingQueue;

import java.util.concurrent.ThreadPoolExecutor;

import java.util.concurrent.TimeUnit;

/**

*

* 描述:

* @author yusong

* @since 1.8

*/

public class HttpServer {

public static void main(String[] args) throws Exception {

// 创建 ServerSocketChannel

ServerSocketChannel serverChannel = ServerSocketChannel.open();

serverChannel.bind(new InetSocketAddress(8080));

// 配置为非阻塞

serverChannel.configureBlocking(false);

// 注册选择器

Selector selector = Selector.open();

serverChannel.register(selector, SelectionKey.OP_ACCEPT);

// 创建线程池

Executor ex = new ThreadPoolExecutor(8, 8, 500, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());

// 创建处理器

while (true) {

// 每次等待0.5秒,0.5秒后返回的就绪通道为0则继续阻塞

if (selector.select(500) == 0) {

continue;

}

// 获取待处理的seletionKey

Iterator it = selector.selectedKeys().iterator();

while (it.hasNext()) {

SelectionKey key = it.next();

HttpHandler httpHandler = new HttpHandler(key);

ex.execute(httpHandler);

}

}

}

// 处理请求

private static class HttpHandler implements Runnable {

// TCP包长度

private int bufferSize = 1024;

// 编码字符集

private String charset = "UTF-8";

// 注册的事件

private SelectionKey key;

public HttpHandler(SelectionKey key) {

this.key = key;

}

// 处理ServerSocketChannel接受请求

public void handleAccept() throws Exception {

ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();

// 接收的客户端的连接

SocketChannel channel = serverChannel.accept();

channel.configureBlocking(false);

// 注册到选择器

channel.register(key.selector(), SelectionKey.OP_READ,

ByteBuffer.allocate(bufferSize));

}

// socketChannel 读取数据

public void handleRead() throws Exception {

// 获取channel

SocketChannel channel = (SocketChannel) key.channel();

// 获取Buffer并重置

ByteBuffer buffer = (ByteBuffer) key.attachment();

buffer.clear();

// 从通道获取内容

if (channel.read(buffer) == -1) {

channel.close();

} else {

// 接受请求数据

buffer.flip();

String reciveMsg = Charset.forName(charset).newDecoder().decode(buffer).toString();

String[] requestContent = reciveMsg.split("\r\n");

for (String line : requestContent) {

System.out.println(line);

if (line.isEmpty()) {

break;

}

}

// 返回客户端

StringBuilder sendMsg = new StringBuilder();

sendMsg.append("HTTP/1.1 200 OK\r\n");// 响应行

// 响应头

sendMsg.append("cache-control: private;\r\n")

.append("content-type: text/html; charset=utf-8\r\n")

.append("\r\n")

// 响应体

.append("")

.append("

测试HttpServer")

.append("

服务端接收到的请求报文

");

for (String line : requestContent) {

sendMsg.append(line+"");

if (line.isEmpty()) {

break;

}

}

sendMsg.append("");

buffer = ByteBuffer.wrap(sendMsg.toString().getBytes(charset));

// 发送

channel.write(buffer);

channel.close();

}

}

@Override

public void run() {

try {

if (key.isAcceptable()) {

handleAccept();

}

if (key.isReadable()) {

handleRead();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

控制台及浏览器打印结果:

f3dcd23407946cb988ea200b2434e8eb.png

930ec3fdc791d9cf6298acd0c115d720.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值