HTTP协议 chunked

最近写了一个自己的http服务器(基于netty,但不使用netty自带的http协议包)。一般的请求都是直接使用指定content-length的方式去实现的,但对于一些大文件的传输效率则不太理想,之前一直只是大概知道分块传输,但一直没有真正码过相关代码,这次就尝试实现了一下。

总共三部分:

1、设置响应头

2、分块传输: 长度\r\n内容\r\n,长度为16进制字符串

3、空数据块:用于标记结束, 0\r\n\r\n

    private String CRLF = "\r\n";

	private void write(ChannelHandlerContext ctx) throws IOException {
		//响应头
		ctx.writeAndFlush(getHeaderByteBuf());
		
		//数据分块传输
		InputStream in = App.class.getClassLoader().getResourceAsStream("jquery-3.0.0.js");
		byte[] bs = new byte[1024];
		int len = 0;
		while((len = in.read(bs)) > 0) {
			ctx.writeAndFlush(getChunkedByteBuf(bs, len));
		}
		
		//空数据块表示结束
		ctx.writeAndFlush(getEnd());
	}
	
	/**
	 * 响应头信息
	 * @return
	 */
	private ByteBuf getHeaderByteBuf() {
		StringBuffer header = new StringBuffer();
		header.append("HTTP/1.1 200 OK").append(CRLF);
		header.append("content-type: application/javascript").append(CRLF);
		header.append("transfer-encoding: chunked").append(CRLF).append(CRLF);
		return Unpooled.copiedBuffer(header.toString().getBytes());
	}
	
	/**
	 * 获取chunked数据块
	 * size(16进制长度)\r\n content(具体内容)\r\n
	 * @param bs
	 * @param len
	 * @return
	 * @throws IOException
	 */
	private ByteBuf getChunkedByteBuf(byte[] bs, int len) throws IOException {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		//size\r\n
		out.write(Integer.toHexString(len).getBytes());
		out.write(CRLF.getBytes());
		
		//content\r\n
		out.write(bs, 0, len);
		out.write(CRLF.getBytes());
		return Unpooled.copiedBuffer(out.toByteArray());
	}
	
	/**
	 * 获取空数据块 0\r\n\r\n
	 * 空数据块是最后传输,表示数据结束
	 * @return
	 */
	private ByteBuf getEnd() {
		StringBuffer contentCount = new StringBuffer("0").append(CRLF).append(CRLF);
		return Unpooled.copiedBuffer(contentCount.toString().getBytes());
	}

 

猜你喜欢

转载自blog.csdn.net/jackycjw/article/details/90814367