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