Toma4.1实现HTTP/1.1持久化处理(以行读取字节流)

1.浏览器在发送数据的时候,如果是get方式,直接发送,如果是 post方式会发送content-length表明发送数据的大小
2.浏览器在接收数据的时候一般都会知道要接收数据的大小,这样浏览器不至于盲目等待和阻塞
3.服务器在读取请求的时候是以一行来读取.那么它是怎么知道读取完所有有头的呢?原因就在头后面的一个\r\n,如果读取这个就表明头结束,不再下读取,这样就不会造成
服务器读取的时候阻塞

4.而服务器发送数据的时候,会将数据大小发送过去,如果是静态html页面的话,就直接 content-length标明,如果是动态的话,以chunked发送,每次write前,将大小write

在解析请求头信息时,tomcat 提供了一个SocketInputStream 来读取socket 中 inputStream 中的信息,将其读取出来

然后进行解析,由于 http请求头格式如果下

XXXX: XXX\r\n

XXXX: XXX\r\n

\r\n

所以,socketInputStream 每次就读取直到 \r\n,然后再次读取,就是形如:

for(;;){

if(buffer[pos] == (byte)'\r')

continue;

} if(buffer[pos]==(byte)'\n')

break;

在读取socket 流时,由于不知道什么时候读取停止,会造成 read() 阻塞,所以,读取时一定要提交明确的停止界限

而 socketInputStream 则是根据最后的 \r\n 来标识的,在 读取前,如果则上来就讲到一个\r\n,则表明读取完毕

下面是一个模仿socketInputStream 流的例子,也是以行来读取字节,遇到 \r\n来结束

package stream;

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 以行读取字节
 * 
 * 
 * 
 */
public class LineInputStream {
    private static final byte CR = (byte) '\r';
    private static final byte LF = (byte) '\n';
    private static final int SIZE = 1024;
    private byte[] buf;
    private int pos;
    private int count;
    private InputStream in;

    public LineInputStream(InputStream in, int size) {
	this.in = in;
	buf = new byte[size];
    }

    public LineInputStream(InputStream in) {
	this(in, SIZE);
    }

    public int read() throws IOException {
	if (pos >= count) {
	    fill();
	    if (pos >= count)
		return -1;
	}
	return buf[pos++] & 0xff;
    }

    /**
     * 一次读取一行,以\r\n为结束标记,读取结束返回 null 读取结束与 EOF 不同,读取结束以 \r\n正学结束,停止外部的循环读取
     * 而EOF不是以 \r\n为结束,而是在\r\n之前流
     * 
     * @return
     * @throws IOException
     */
    public String readLine() throws IOException {
	StringBuilder sb = new StringBuilder();
	int ch = read();
	if (ch == -1)
	    throw new EOFException(); // 表明流结束,如果是socket,则表明socket.close()
	if (ch == CR || ch == LF) { // 如果刚开始就讲到了\r\n,表明必送结束
	    read();
	    return null;
	}
	pos--;
	while (true) {
	    if (pos >= count) {
		fill();
		if (pos >= count)
		    return sb.toString();
	    }
	    if (buf[pos] == CR) {
		pos++;
		continue;
	    }
	    if (buf[pos] == LF) {
		pos++;
		break;
	    }
	    sb.append((char) (buf[pos++] & 0xff));
	}
	return sb.toString();
    }

    public int readLine(byte[] buffer, int offset, int len) throws IOException {
	// 进行参数化检查
	if (buffer == null)
	    throw new NullPointerException();
	if (offset < 0 || offset > buffer.length || len < 0
		|| offset + len > buffer.length)
	    throw new ArrayIndexOutOfBoundsException();
	int allBits = 0;
	int ch = read();
	if (ch == -1)
	    return -1; 
	if (ch == CR || ch == LF)
	    return -1;
	pos--;
	while(true) {
	    if(pos>=count)
	    {
		fill();
		if(pos>=count)
		    return allBits;
	    }
	    if(buf[pos]==CR)
	    {
		pos++;
		continue;
	    }
	    if(buf[pos]==LF || allBits==len) {
		pos++;
		break;
	    }
	    buffer[allBits++] = buf[pos++];
	    
	}
	return allBits;
    }

    /*
     * 在 pos>=count时,也就是buf数据读完时才fill
     */

    private void fill() throws IOException {
	pos = 0;
	count = 0;
	int len = in.read(buf);
	if (len > 0) // 否则流就关闭了
	    count = len;
    }

    public static void main(String args[]) throws Exception {
	LineInputStream lin = new LineInputStream(new FileInputStream(
		"F:\\c.txt"), 4);
	/*String line = null;

	while ((line = lin.readLine()) != null) {
	    System.out.println(line);
	}*/
	byte[] buffer = new byte[100];
	int len = -1;
	
	while((len=lin.readLine(buffer, 0, buffer.length))!=-1) {
	   System.out.println(new String(buffer,0,len));
	}

    }

}


你可能感兴趣的:(Toma4.1实现HTTP/1.1持久化处理(以行读取字节流))