﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Look into it ~-随笔分类-协议</title><link>http://www.blogjava.net/lukewange-hit1983/category/34539.html</link><description>present</description><language>zh-cn</language><lastBuildDate>Tue, 11 Nov 2008 02:52:02 GMT</lastBuildDate><pubDate>Tue, 11 Nov 2008 02:52:02 GMT</pubDate><ttl>60</ttl><item><title>j2me 联网技术分析总结</title><link>http://www.blogjava.net/lukewange-hit1983/archive/2008/11/04/238629.html</link><dc:creator>LukeW</dc:creator><author>LukeW</author><pubDate>Tue, 04 Nov 2008 08:22:00 GMT</pubDate><guid>http://www.blogjava.net/lukewange-hit1983/archive/2008/11/04/238629.html</guid><wfw:comment>http://www.blogjava.net/lukewange-hit1983/comments/238629.html</wfw:comment><comments>http://www.blogjava.net/lukewange-hit1983/archive/2008/11/04/238629.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lukewange-hit1983/comments/commentRss/238629.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lukewange-hit1983/services/trackbacks/238629.html</trackback:ping><description><![CDATA[<strong>基本点:</strong><br />
<p><strong>Generic Connections</strong></p>
<p>
In the CLDC Generic Connection framework, all connections are created using
the <code>open</code> static method from the <code>Connector</code> class. If
successful, this method returns an object that implements one of the generic
connection interfaces. Figure 1 shows how these interfaces form an <em>is-a</em>
hierarchy. The <code>Connection</code> interface is the base interface such
that <code>StreamConnectionNotifier</code> <em>is a</em> <code>Connection</code> and
<code>InputConnection</code> <em>is a</em> <code>Connection</code> too.
</p>
<center>
<img src="http://developers.sun.com/mobility/images/network_fig1.gif" alt="fig1.gif" width="435" height="357" /><br />
Figure 1: Connection interface hierarchy
</center>
<ul>
    <li>The <code>Connection</code> interface is the most basic connection type. It
    can only be opened and closed.</li>
    <li>The <code>InputConnection</code> interface represents a device from which
    data can be
    read. Its <code>openInputStream</code> method returns an input stream for the
    connection.
    </li>
    <li>The <code>OuputConnection</code> interface represents a device to which data
    can be
    written. Its <code>openOutputStream</code> method returns an output stream for
    the connection.
    </li>
    <li>The <code>StreamConnection</code> interface combines the input and output
    connections.
    </li>
    <li>The <code>ContentConnection</code> is a subinterface of
    <code>StreamConnection</code>. It
    provides access to some of the basic meta data information provided by HTTP
    connections.
    </li>
    <li>The <code>StreamConnectionNotified</code> waits for a connection to be
    established.
    It returns a <code>StreamConnection</code> on which a communication link has ben
    established.
    </li>
    <li>The <code>DatagramConnection</code> represents a datagram endpoint.</li>
</ul>
<p>
The <code>open</code> method of the <code>Connector</code> class has the
following syntax, where the <code>String</code> parameter has the format
<code>"protocol:address;parameters"</code>.
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Connector.open(String);</span></div>
<p>
Here are a few examples:
</p>
<p>
<strong>HTTP Connection</strong>
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Connector.open(</span><span style="color: #000000;">"</span><span style="color: #000000;">http://java.sun.com/developer</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<p>
<strong>Datagram Connection</strong>
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Connector.open(</span><span style="color: #000000;">"</span><span style="color: #000000;">datagram://address:port#</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<p>
<strong>Communicate with a Port</strong></p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Connector.open(</span><span style="color: #000000;">"</span><span style="color: #000000;">comm:0;baudrate=9600');</span></div>
<p>
</p>
<p>
<strong>Open Files</strong><br />
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">Connector.open(</span><span style="color: #000000;">"</span><span style="color: #000000;">file:/myFile.txt</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br />
<strong><br />
</strong><strong>The HttpConnection Interface</strong>:<br />
<br />
The HTTP protocol is a request-response application protocol in which the
parameters of the request must be set before the request is sent. The connection
could be in one of the three following states:
<ul>
    <li>Setup: No connection yet</li>
    <li>Connected: Connection has been made, the request has been sent, and some
    response is
    expected</li>
    <li>Closed: Connection is closed</li>
</ul>
<p>
In the <strong>setup</strong> state the following methods can be invoked:
</p>
<ul>
    <li><code>setRequestMethod</code>
    </li>
    <li><code>setRequestProperty</code></li>
</ul>
<p>
For example, suppose you have this connection: <br />
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">HttpConnection&nbsp;c&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;(HttpConnection)<br />
Connector.open(</span><span style="color: #000000;">"</span><span style="color: #000000;">http://java.sun.com/developer</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<p>
Then, you can set the request method to be of type <code>POST</code> as follows:
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">c.setRequestMethod(HttpConnection.POST);</span></div>
<p>
And likewise, you can set some of the HTTP properties. For example, you
can set the <code>User-Agent</code> as follows:</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">c.setRequestProperty(</span><span style="color: #000000;">"</span><span style="color: #000000;">User-Agent</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="color: #000000;">Profile/MIDP-1.0&nbsp;Configuration/CLDC-1.0</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br />
<p>
If there is a method that requires data to be sent or received from the
server, there is a state transition from <strong>Setup</strong> to <strong>Connected</strong>.
Examples of methods that cause the transition include:
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">openInputStream<br />
openOutputStream<br />
openDataInputStream<br />
openDataOutputStream<br />
getLength<br />
getType<br />
getDate<br />
getExpiration</span></div>
<p>
And while the connection is open, some of these methods that may
be invoked:
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">getURL<br />
getProtocol<br />
getHost<br />
getPort</span></div>
<img src="http://developers.sun.com/im/a.gif" alt=" " border="0" width="1" height="4" /><strong><br />
<br />
------------------------------------------------------------<br />
要注意的问题:<br />
</strong>开发中遇到个很头疼的问题, 与服务器通信write()数据时报java.io.IOException: Couldn't write to socket.<br />
但是服务器抓不到任何包. 一开始怀疑是连建立连接出的问题, 实际上服务器抓不到包也有可能是流在没有close的时候就已经报错了.<br />
如:<br />
conn.open("url");<br />
out = conn.openDataOutputStream();//此时将进行与服务器的三次握手;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //但是如果在out.close()之前出现异常服务器是抓不到任何包的<br />
out.write(byte[] bb);<br />
<br />
关于这个的解释应该是流的缓冲机制.<br />
所以正确的写法应该是捕捉到异常之后在catch块中把流close掉<strong>.<br />
</strong>服务器端开发人员一般会说收不到包所以连接有问题,会把责任推给客户端,抓住这个证据在跟服务器端的同事扯皮时将处于有利的位置,嘎嘎.<strong><br />
<span style="color: red;">还有就是要多做小实验, 注意代码要规范严格.</span><br />
<br />
发现的几个问题:</strong><br />
1. java.io.IOException: Couldn't write to socket <br />
<br />
2.
<em>java</em>.<em>io</em>.<em>IOException</em>: <em>Couldn't read from socket</em><br />
<br />
<strong>CMNET联网方案:<br />
<br />
CMWAP联网方案:<br />
<br />
移动资费页的处理:<br />
<br />
一个通用的HTTP连接封装:</strong><br />
<img src ="http://www.blogjava.net/lukewange-hit1983/aggbug/238629.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lukewange-hit1983/" target="_blank">LukeW</a> 2008-11-04 16:22 <a href="http://www.blogjava.net/lukewange-hit1983/archive/2008/11/04/238629.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTTP协议中的Tranfer-Encoding：chunked编码解析</title><link>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230952.html</link><dc:creator>LukeW</dc:creator><author>LukeW</author><pubDate>Wed, 24 Sep 2008 10:03:00 GMT</pubDate><guid>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230952.html</guid><wfw:comment>http://www.blogjava.net/lukewange-hit1983/comments/230952.html</wfw:comment><comments>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lukewange-hit1983/comments/commentRss/230952.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lukewange-hit1983/services/trackbacks/230952.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 当不能预先确定报文体的长度时，不可能在头中包含Content-Length域来指明报文体长度，此时就需要通过Transfer-Encoding域来确定报文体长度。<br />
&nbsp;&nbsp;&nbsp; 通常情况下，Transfer-Encoding域的值应当为chunked,表明采用chunked编码方式来进行报文体的传输。chunked编码是HTTP/1.1 RFC里定义的一种编码方式，因此所有的HTTP/1.1应用都应当支持此方式。<br />
&nbsp;&nbsp;&nbsp; chunked编码的基本方法是将大块数据分解成多块小数据，每块都可以自指定长度，其具体格式如下（BNF文法）:<br />
&nbsp;&nbsp;&nbsp; Chunked-Body&nbsp;&nbsp; = *chunk&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp; //0至多个chunk<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last-chunk&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp; //最后一个chunk <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; trailer&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  //尾部<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CRLF&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp; //结束标记符<br />
<br />
&nbsp;&nbsp; chunk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = chunk-size [ chunk-extension ] CRLF&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chunk-data CRLF<br />
&nbsp;&nbsp; chunk-size&nbsp;&nbsp;&nbsp;&nbsp; = 1*HEX<br />
&nbsp;&nbsp; last-chunk&nbsp;&nbsp;&nbsp;&nbsp; = 1*("0") [ chunk-extension ] CRLF<br />
<br />
&nbsp;&nbsp; chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )<br />
&nbsp;&nbsp; chunk-ext-name = token<br />
&nbsp;&nbsp; chunk-ext-val&nbsp; = token | quoted-string<br />
&nbsp;&nbsp; chunk-data&nbsp;&nbsp;&nbsp;&nbsp; = chunk-size(OCTET)<br />
&nbsp;&nbsp; trailer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = *(entity-header CRLF)&nbsp;&nbsp;  &nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 解释：<br />
&nbsp;&nbsp;&nbsp;
Chunked-Body表示经过chunked编码后的报文体。报文体可以分为chunk,
last-chunk，trailer和结束符四部分。chunk的数量在报文体中最少可以为0，无上限；每个chunk的长度是自指定的，即，起始的数
据必然是16进制数字的字符串，代表后面chunk-data的长度（字节数）。这个16进制的字符串第一个字符如果是&#8220;0&#8221;，则表示chunk-
size为0，该chunk为last-chunk,无chunk-data部分。可选的chunk-extension由通信双方自行确定，如果接收者
不理解它的意义，可以忽略。<br />
&nbsp;&nbsp;&nbsp; trailer是附加的在尾部的额外头域，通常包含一些元数据（metadata, meta means "about information"），这些头域可以在解码后附加在现有头域之后。<br />
&nbsp;&nbsp;&nbsp; 实例分析：<br />
&nbsp;&nbsp;&nbsp; 下面分析用ethereal抓包使用Firefox与某网站通信的结果（从头域结束符后开始）：<br />
Address&nbsp; 0..........................&nbsp; f<br />
000c0&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 31<br />
000d0 &nbsp;&nbsp; 66 66 63 0d 0a ...............&nbsp;&nbsp; // ASCII码:1ffc"r"n, chunk-data数据起始地址为000d5<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 很明显，&#8220;1ffc&#8221;为第一个chunk的chunk-size,转换为int为8188.由于1ffc后马上就是<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CRLF,因此没有chunk-extension.chunk-data的起始地址为000d5, 计算可知下一块chunk的起始<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp; 地址为000d5+1ffc + 2=020d3,如下：<br />
020d0&nbsp;&nbsp;&nbsp; .. 0d 0a 31 66 66 63 0d 0a .... // ASCII码:"r"n1ffc"r"n<br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 前一个0d0a是上一个chunk的结束标记符，后一个0d0a则是chunk-size和chunk-data的分隔符。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp; 此块chunk的长度同样为8188, 依次类推，直到最后一块<br />
100e0&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp; 0d  0a 31<br />
100f0&nbsp;&nbsp;&nbsp;  65 61 39 0d 0a......&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp; //ASII码："r"n"1ea9"r"n<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp; 此块长度为0x1ea9 = 7849, 下一块起始为100f5 + 1ea9 + 2 = 11fa0,如下：<br />
100a0&nbsp;&nbsp;&nbsp; 30 0d 0a 0d 0a&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp; //ASCII码：0"r"n"r"n<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp; &#8220;0&#8221;说明当前chunk为last-chunk, 第一个0d 0a为chunk结束符。第二个0d0a说明没有trailer部分，整个Chunk-body结束。<br />
&nbsp;&nbsp;&nbsp; 解码流程：<br />
&nbsp;&nbsp;&nbsp; 对chunked编码进行解码的目的是将分块的chunk-data整合恢复成一块作为报文体，同时记录此块体的长度。<br />
&nbsp;&nbsp;&nbsp; RFC2616中附带的解码流程如下：(伪代码）<br />
&nbsp;&nbsp;&nbsp; length := 0&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  //长度计数器置0<br />
&nbsp;&nbsp;&nbsp; read chunk-size, chunk-extension (if any) and CRLF&nbsp;&nbsp;  &nbsp;&nbsp;  //读取chunk-size, chunk-extension<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp; //和CRLF<br />
&nbsp;&nbsp;&nbsp; while(chunk-size &gt; 0 )&nbsp;&nbsp; {&nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  //表明不是last-chunk<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  read chunk-data and CRLF&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  //读chunk-size大小的chunk-data,skip CRLF<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;  append chunk-data to entity-body&nbsp;&nbsp;  &nbsp; //将此块chunk-data追加到entity-body后<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  read chunk-size and CRLF &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  //读取新chunk的chunk-size 和 CRLF<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; read entity-header&nbsp;&nbsp;  &nbsp;&nbsp;  //entity-header的格式为name:valueCRLF,如果为空即只有CRLF<br />
&nbsp;&nbsp;&nbsp; while （entity-header not empty)&nbsp;&nbsp; //即，不是只有CRLF的空行<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  append  entity-header to existing header fields<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  read entity-header<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; Content-Length:=length&nbsp;&nbsp;  &nbsp;&nbsp;  //将整个解码流程结束后计算得到的新报文体length<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp; //作为Content-Length域的值写入报文中<br />
&nbsp;&nbsp;&nbsp; Remove "chunked" from Transfer-Encoding&nbsp; //同时从Transfer-Encoding中域值去除chunked这个标记<br />
&nbsp;&nbsp;&nbsp; length最后的值实际为所有chunk的chunk-size之和，在上面的抓包实例中，一共有八块chunk-size为0x1ffc(8188)的chunk,剩下一块为0x1ea9(7849),加起来一共73353字节。<br />
&nbsp;&nbsp;&nbsp; 注：对于上面例子中前几个chunk的大小都是8188,可能是因为:"1ffc" 4字节，""r"n"2字节，加上块尾一个""r"n"2字节一共8字节，因此一个chunk整体为8196,正好可能是发送端一次TCP发送的缓存大小。
<img src ="http://www.blogjava.net/lukewange-hit1983/aggbug/230952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lukewange-hit1983/" target="_blank">LukeW</a> 2008-09-24 18:03 <a href="http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTTP Connections</title><link>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230951.html</link><dc:creator>LukeW</dc:creator><author>LukeW</author><pubDate>Wed, 24 Sep 2008 10:01:00 GMT</pubDate><guid>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230951.html</guid><wfw:comment>http://www.blogjava.net/lukewange-hit1983/comments/230951.html</wfw:comment><comments>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230951.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/lukewange-hit1983/comments/commentRss/230951.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lukewange-hit1983/services/trackbacks/230951.html</trackback:ping><description><![CDATA[<div style="text-align: center;"><strong>HTTP Connections</strong><br />
</div>
最近初涉网络编程，分析了下HTTP协议，下面为第一篇关于HTTP连接控制方面的学习日志，主要参考RFC2616，肯定有疏漏之处，还望指出。<br />
HTTP协议是位于传输层之上的应用层协议，其网络层基础通常是TCP协议。TCP协议是面向连接和流的，因此连接的状态和控制对于HTTP协议而言相当重要。同时，HTTP是基于报文的，因此如何确定报文长度也是协议中比较重要的一点。<br />
<span style="font-weight: bold;">Persistent Connections持久连接</span><br />
<span style="font-weight: bold;">目的</span><br />
&nbsp;&nbsp;&nbsp; 在使用持久连接前，HTTP协议规定为获取每个URL资源都需要使用单独的一个TCP连接，这增加了HTTP服务端的负载，引起互联网拥塞。例如内嵌图片以及其他类似数据的使用要求一个客户端在很短时间内向同一个服务端发起多个请求。<br />
使用持久连接的优点:<br />
减少TCP连接数量<br />
在一个连接上实现HTTP请求和应答的流水，即允许客户端发出多个请求，而不必在接收到前一请求的应答后才发出下一请求，极大减少时间消耗<br />
后续请求延迟减少，无需再在TCP握手上耗时<br />
可以更加优雅地实现HTTP协议，由于持续连接的存在无需报告错误后无需关闭连接，因此客户端可使用最新的协议特性发出请求，如果接收到表示错误的应答，则换用更旧的语义。<br />
<br />
<span style="font-weight: bold;">总体描述</span><br />
HTTP/1.1和之前版本的显著区别是HTTP/1.1默认使用持久连接。即，除非服务端在应答中明确指出，客户端应当假定服务端会维持一个持久连接，即使从服务端收到的应答是报告错误。<br />
持
久连接对关闭TCP连接的行为提供信号量机制支持。这个信号量是在HTTP头中的Connection域设置，注意Client向Proxy发出请求时该
域可能被Proxy-Connection域替换。一旦close信号被表明，客户端绝不能再通过该连接发送更多的请求。<br />
<br />
<span style="font-weight: bold;">协商(Negotiation)</span><br />
HTTP/1.1
服务端可以假定HTTP/1.1客户端会维持持久连接，除非请求中Connection域的值是"close".同样的，如果服务端打算在送出应答后立即
关闭连接，它应当在应答中包含同样的Connection域。(TCP连接关闭是双向的,此时TCP进入半关闭状态)<br />
同样的，HTTP/1.1客户端可以期望连接是持久的，除非如前所述收到表示连接关闭的应答。当然，也可以主动发出一个包含Connection:close的请求以表明终止连接。<br />
无论客户端还是服务端发出的报文包含Connection:close，则该请求均为连接上的最后一个请求(服务端发出此应答后关闭，因此不可能接收更多的请求)<br />
<span style="font-weight: bold;">报文传输长度</span><br />
&nbsp;&nbsp;&nbsp; 为保证持久性，连接上的报文都必须有一个自定义的报文传输长度(否则必须通过连接的关闭表示报文结束，因为TCP连接是面向流的)，确定的规则按优先级由高到低排列如下：<br />
&nbsp;&nbsp;&nbsp; 报文传输长度指报文中出现的报文体的长度(即，不包括头长度，因为报文头的结束可通过连续两个CRLF确定）<br />
1.任何绝不能包含报文体(如1xx,204,304)的应答消息总是以头域后的第一个空行结束,无视头中所有的entity类型域的设置，包括Content-Length域。<br />
2.Transfer-Encoding域出现，其值为除"identify"以外的其他值，则用"chunked"传输编码方式确定传输长度，具体方式留待下篇分析。<br />
3.Content-
Length域出现，且Transfer-Encoding域未出现(出现则忽略Content-Length域)。Content-Length域的值
为十进制数的字节序，如Content-Length：1234，则1、2、3、4是分别作为一个octet传输的，因此需要atoi转换成数值。<br />
4.如果报文使用了"multipart/byteranges"的媒体类型，且没对传输长度做前面的指明，则这种自分割的媒体类型定义了传输长度。具体参见Range头域的说明。<br />
5.服务端关闭连接(此方法不可用于客户端发出的请求报文，因为客户端关闭连接则使得服务端无法发送应答).<br />
&nbsp;&nbsp;&nbsp;
为保持和HTTP/1.0的兼容性,
包含报文体的HTTP/1.1请求必须包含合法的Content-Length头域,除非明确知道服务端是HTTP/1.1兼容的.如果请求包含消息体,
而没有Content-Length域,那么如果服务端无法确定消息长度时,它会返回400(无效请求),或者坚持获取合法Content-Length
而返回411(要求包含长度).<br />
<br />
&nbsp;&nbsp;&nbsp; 所有接收实体的HTTP/1.1应用程序必须接受"chunked"传输编码, 这样允许当报文长度无法预先确定时可以运用此机制获取报文长度.<br />
&nbsp;&nbsp;&nbsp; 报文不能同时包含Content-Length头域和非"identity" Transfer-Encoding.如果出现了, Content-Length域必须被忽略.<br />
&nbsp;&nbsp;&nbsp; 当Content-Length域在允许报文体的报文中存在时, 其域值必须严格等于消息体中的8比特字节.HTTP/1.1 user agent 必须在接收并检测到一个错误的长度时提醒用户.<br />
&nbsp;&nbsp;&nbsp; 以上方法中，最常见的还是使用Content-Length域表示报文体长度，Transfer-Encoding需要按格式解码才能还原出发送编码前的报文。<br />
<br />
<span style="font-weight: bold;">流水</span><br />
&nbsp;&nbsp;&nbsp; 支持持久连接的客户端可以流水发送请求，服务端必须按发送的顺序发送应答。<br />
&nbsp;&nbsp;&nbsp; 假定持久连接和连接后即可流水的客户端应当做好在第一次流水失败后重新尝试此连接。在这样的尝试中，在确定连接是持久的之前，客户端不能再流水。<br />
&nbsp;&nbsp;&nbsp; 客户端同样必须准备好在服务端送回所有相关应答前就关闭连接时重发请求。<br />
&nbsp;&nbsp;&nbsp; 不应流水non-idempotent方法<br />
<br />
<span style="font-weight: bold;">Proxy Servers</span><br />
&nbsp;&nbsp;&nbsp; 对于代理服务端而言，正确实现Connection头域指定的属性尤为重要。<br />
&nbsp;&nbsp;&nbsp; 代理服务端必须分立通告它的客户端和连接的原始服务端持久连接的属性，每个持久连接设置仅针对一个传输连接。<br />
&nbsp;&nbsp;&nbsp; <br />
<span style="font-weight: bold;">实践考量</span><br />
&nbsp;&nbsp;&nbsp; 超时值，服务端通常会为每个连接维护一个定时器，一旦某个连接不活跃超过一定时间值，服务端会关闭此连接。考虑到一个客户端可能通过代理服务端发出更多连接，代理服务端通常会将超时值设置得更高。<br />
&nbsp;&nbsp;&nbsp; 还有一些关于从异步关闭中恢复的讨论。<br />
<br />
<span style="font-weight: bold;">报文传输要求</span><br />
&nbsp;&nbsp;&nbsp; 使用TCP流控制来解决服务端临时负载过高问题，而不是简单的依赖客户端重连而关闭连接。<br />
&nbsp;&nbsp;&nbsp; 监视连接情况以获取错误状态消息<br />
&nbsp;&nbsp;&nbsp; 关于使用100(继续)状态码<br />
&nbsp;&nbsp;&nbsp; 100状态码用于客户端发送请求体之前测试是否可以发送该请求，对于Proxy，有以下要求：<br />
1.如果代理服务端接收到包含Expect头域值为"100-continue"的请求, 而不明确知道下一跳服务不支持HTTP/1.1以上版本, 则它必须转发这个请求, 包括Expect头域.<br />
2.如果代理知道下一跳服务端为HTTP/1.0或者更低版本, 则它不能转发此请求, 且必须以407应答客户端.<br />
3.如果明确知道发出请求的客户端版本为HTTP/1.0或者更低，则代理服务端绝不能转发100应答,这条规则凌驾于转发1xx应答的一般准则.<br />
<br />
<span style="font-weight: bold;">Connection头域说明</span><br />
BNF文法：<br />
&nbsp;&nbsp;&nbsp; Connection = "Connection" ":" 1#(connection-token)<br />
&nbsp;&nbsp;&nbsp; connection-token&nbsp; = token<span style="font-style: italic;"><br />
&nbsp;&nbsp;&nbsp; </span>Connection头域中的token用于指定对于特定连接有意义的选项，因此proxy在转发前要扫描此域，从头中去除和token同名的域。例如Connection:Range,则要去掉Range域。<br />
&nbsp;&nbsp;&nbsp; HTTP/1.1定义了close这个token，发送者用此token表示在完成这个报文所属请求/应答的收发后连接将关闭。<br />
<br />
<br />
<img src ="http://www.blogjava.net/lukewange-hit1983/aggbug/230951.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lukewange-hit1983/" target="_blank">LukeW</a> 2008-09-24 18:01 <a href="http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230951.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于断点续传的调研</title><link>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230950.html</link><dc:creator>LukeW</dc:creator><author>LukeW</author><pubDate>Wed, 24 Sep 2008 09:57:00 GMT</pubDate><guid>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230950.html</guid><wfw:comment>http://www.blogjava.net/lukewange-hit1983/comments/230950.html</wfw:comment><comments>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230950.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lukewange-hit1983/comments/commentRss/230950.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lukewange-hit1983/services/trackbacks/230950.html</trackback:ping><description><![CDATA[一些讨论:<br />
http://topic.csdn.net/t/20061214/22/5231907.html
<img src ="http://www.blogjava.net/lukewange-hit1983/aggbug/230950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lukewange-hit1983/" target="_blank">LukeW</a> 2008-09-24 17:57 <a href="http://www.blogjava.net/lukewange-hit1983/archive/2008/09/24/230950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTTP头信息</title><link>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/10/228111.html</link><dc:creator>LukeW</dc:creator><author>LukeW</author><pubDate>Wed, 10 Sep 2008 04:05:00 GMT</pubDate><guid>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/10/228111.html</guid><wfw:comment>http://www.blogjava.net/lukewange-hit1983/comments/228111.html</wfw:comment><comments>http://www.blogjava.net/lukewange-hit1983/archive/2008/09/10/228111.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lukewange-hit1983/comments/commentRss/228111.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lukewange-hit1983/services/trackbacks/228111.html</trackback:ping><description><![CDATA[<p>HTTP（HyperTextTransferProtocol）是超文本传输协议的缩写，它用于传送WWW方式的数据，关于HTTP
协议的详细内容请参
考RFC2616。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求，请求头包含请求的方法、URI、协议版本、以及包含请求修饰符、客户
信息和内容的类似于MIME的消息结构。服务器以一个状态行作为响应，相应的内容包括消息协议的版本，成功或者错误编码加上包含服务器信息、实体元信息以
及可能的实体内容。 <br />
<br />
通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行，
一个或者多个头域，一个只是头域结束的空行和可
选的消息体组成。<span style="color: #ff9658;">HTTP的头域包括通用头，请求头，响应头和实体头四个部分</span>。每个头域由一个域名，冒号（:）和域值三部分组成。域名是大小写无关的，域
值前可以添加任何数量的空格符，头域可以被扩展为多行，在每行开始处，使用至少一个空格或制表符。 <br />
<br />
<strong><span style="font-size: 24pt;"><span style="font-size: 18pt;">通用头域</span> </span><br />
</strong>
通用头 域包含请求和响应消息都支持的头域，通用头域包含Cache-Control、
Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via。对通用头域的扩展要求通讯双方都支持此扩
展，如果存在不支持的通用头域，一般将会作为实体头域处理。下面简单介绍几个在UPnP消息中使用的通用头域。 <br />
<br />
<br />
<strong>　　Cache-Control头域</strong> <br />
Cache -Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置
Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、
max-stale、min-fresh、only-if-cached，响应消息中的指令包括public、private、no-cache、no-
store、no-transform、must-revalidate、proxy-revalidate、max-age。各个消息中的指令含义如
下： <br />
<br />
Public指示响应可被任何缓存区缓存。 <br />
Private指示对于单个用户的整个或部分响应消息，不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息，此响应消息对于其他用户的请求无效。 <br />
no-cache指示请求或响应消息不能缓存 <br />
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。 <br />
max-age指示客户机可以接收生存期不大于指定时间（以秒为单位）的响应。 <br />
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。 <br />
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值，那么客户机可以接收超出超时期指定值之内的响应消息。 <br />
<br />
<br />
<strong>　　Date头域</strong> <br />
Date头域表示消息发送的时间，时间的描述格式由rfc822定义。例如，Date:Mon,31Dec200104:25:57GMT。Date描述的时间表示世界标准时，换算成本地时间，需要知道用户所在的时区。 <br />
<br />
<strong>　　Pragma头域 <br />
</strong>　　Pragma头域用来包含实现特定的指令，最常用的是Pragma:no-cache。在HTTP/1.1协议中，它的含义和Cache- Control:no-cache相同。 <br />
<br />
<strong><span style="font-size: 18pt;">请求消息</span></strong> <br />
请求消息的第一行为下面的格式： <br />
MethodSPRequest-URISPHTTP-VersionCRLFMethod
表示对于Request-URI完成的方法，这个字段是大小写敏感的，包括OPTIONS、GET、HEAD、POST、PUT、DELETE、
TRACE。方法GET和HEAD应该被所有的通用WEB服务器支持，其他所有方法的实现是可选的。GET方法取回由Request-URI标识的信息。
HEAD方法也是取回由Request-URI标识的信息，只是可以在响应时，不返回消息体。POST方法可以请求服务器接收包含在请求中的实体信息，可
以用于提交表单，向新闻组、BBS、邮件群组和数据库发送消息。 <br />
<br />
SP表示空格。Request-URI遵循URI格式，在此字段
为星 号（*）时，说明请求并不用于某个特定的资源地址，而是用于服务器本身。HTTP-
Version表示支持的HTTP版本，例如为HTTP/1.1。CRLF表示换行回车符。请求头域允许客户端向服务器传递关于请求或者关于客户机的附加
信息。请求头域可能包含下列字段Accept、Accept-Charset、Accept-
Encoding、Accept-Language、Authorization、From、Host、If-Modified-Since、If-
Match、If-None-Match、If-Range、If-Range、If-Unmodified-Since、Max-Forwards、
Proxy-Authorization、Range、Referer、User-Agent。对请求头域的扩展要求通讯双方都支持，如果存在不支持的请
求头域，一般将会作为实体头域处理。 <br />
<br />
<strong>　　典型的请求消息：</strong> <br />
GET http://download.microtool.de:80/somedata.exe <br />
Host: download.microtool.de <br />
Accept:*/* <br />
Pragma: no-cache <br />
Cache-Control: no-cache <br />
Referer: http://download.microtool.de/ <br />
User-Agent:Mozilla/4.04[en](Win95;I;Nav) <br />
Range:bytes=554554- <br />
<br />
上例第一行表示HTTP客户端（可能是浏览器、下载程序）通过GET方法获得指定URL下的文件。棕色的部分表示请求头域的信息，绿色的部分表示通用头部分。 <br />
<br />
<strong>　　Host头域 <br />
</strong>　　Host头域指定请求资源的Intenet主机和端口号，必须表示请求url的原始服务器或网关的位置。HTTP/1.1请求必须包含主机头域，否则系统会以400状态码返回。 <br />
<br />
<strong>　　Referer头域</strong> <br />
Referer
头域允许客户端指定请求uri的源资源地址，这可以允许服务器生成回退链表，可用来登陆、优化cache等。他也允许废除的或错误的连接由于维护的目的被
追踪。如果请求的uri没有自己的uri地址，Referer不能被发送。如果指定的是部分uri地址，则此地址应该是一个相对地址。 <br />
<br />
<strong>　　Range头域</strong> <br />
Range头域可以请求实体的一个或者多个子范围。例如， <br />
表示头500个字节：bytes=0-499 <br />
表示第二个500字节：bytes=500-999 <br />
表示最后500个字节：bytes=-500 <br />
表示500字节以后的范围：bytes=500- <br />
第一个和最后一个字节：bytes=0-0,-1 <br />
同时指定几个范围：bytes=500-600,601-999 <br />
<br />
但是服务器可以忽略此请求头，如果无条件GET包含Range请求头，响应会以状态码206（PartialContent）返回而不是以200 （OK）。 <br />
<br />
<strong>　　User-Agent头域</strong> <br />
User-Agent头域的内容包含发出请求的用户信息。 <br />
<br />
<strong><span style="font-size: 18pt;">响应消息</span></strong> <br />
响应消息的第一行为下面的格式： <br />
HTTP-VersionSPStatus-CodeSPReason-PhraseCRLF <br />
<br />
HTTP -Version表示支持的HTTP版本，例如为HTTP/1.1。Status-
Code是一个三个数字的结果代码。Reason-Phrase给Status-Code提供一个简单的文本描述。Status-Code主要用于机器自
动识别，Reason-Phrase主要用于帮助用户理解。Status-Code的第一个数字定义响应的类别，后两个数字没有分类的作用。第一个数字可
能取5个不同的值： <br />
<br />
1xx:信息响应类，表示接收到请求并且继续处理 <br />
2xx:处理成功响应类，表示动作被成功接收、理解和接受 <br />
3xx:重定向响应类，为了完成指定的动作，必须接受进一步处理 <br />
4xx:客户端错误，客户请求包含语法错误或者是不能正确执行 <br />
5xx:服务端错误，服务器不能正确执行一个正确的请求 <br />
<br />
响应头域允许服务器传递不能放在状态行的附加信息，这些域主要描述服务器的信息和
Request-URI进一步的信息。响应头域包含Age、Location、Proxy-Authenticate、Public、Retry-
After、Server、Vary、Warning、WWW-Authenticate。对响应头域的扩展要求通讯双方都支持，如果存在不支持的响应头
域，一般将会作为实体头域处理。 <br />
<br />
典型的响应消息： <br />
<br />
HTTP/1.0200OK <br />
Date:Mon,31Dec200104:25:57GMT <br />
Server:Apache/1.3.14(Unix) <br />
Content-type:text/html <br />
Last-modified:Tue,17Apr200106:46:28GMT <br />
Etag:"a030f020ac7c01:1e9f" <br />
Content-length:39725426 <br />
Content-range:bytes554554-40279979/40279980 <br />
<br />
上例第一行表示HTTP服务端响应一个GET方法。棕色的部分表示响应头域的信息，绿色的部分表示通用头部分，红色的部分表示实体头域的信息。 <br />
<br />
<strong>　　Location响应头</strong> <br />
Location响应头用于重定向接收者到一个新URI地址。 <br />
<br />
<strong>　　Server响应头</strong> <br />
Server响应头包含处理请求的原始服务器的软件信息。此域能包含多个产品标识和注释，产品标识一般按照重要性排序。 <br />
<br />
<strong>　　实体</strong> <br />
请求消息和响应消息都可以包含实体信息，实体信息一般由实体头域和实体组成。实体头域包含关于实体的原信息，实体头包括Allow、Content-
Base、Content-Encoding、Content-Language、
Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、
Etag、Expires、Last-Modified、extension-header。extension-header允许客户端定义新的实体
头，但是这些域可能无法未接受方识别。实体可以是一个经过编码的字节流，它的编码方式由Content-Encoding或Content-Type定
义，它的长度由Content-Length或Content-Range定义。 <br />
<br />
<strong>　　Content-Type实体头</strong> <br />
Content-Type实体头用于向接收方指示实体的介质类型，指定HEAD方法送到接收方的实体介质类型，或GET方法发送的请求介质类型 Content-Range实体头 <br />
Content-Range实体头用于指定整个实体中的一部分的插入位置，他也指示了整个实体的长度。在服务器向客户返回一个部分响应，它必须描述响应覆盖的范围和整个实体长度。一般格式： <br />
Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-legth&nbsp;</p>
<p><br />
例如，传送头500个字节次字段的形式：Content-Range:bytes0-
499/1234如果一个http消息包含此节（例如，对范围请求的响应或对一系列范围的重叠请求），Content-Range表示传送的范围，
Content-Length表示实际传送的字节数。 <br />
<br />
<strong>　　Last-modified实体头</strong> <br />
</p>
<table align="center" border="1" cellpadding="0" cellspacing="0" width="600">
    <tbody>
        <tr>
            <td>应答头 </td>
            <td>说明 </td>
        </tr>
        <tr>
            <td>Allow </td>
            <td>服务器支持哪些请求方法（如GET、POST等）。</td>
        </tr>
        <tr>
            <td>Content-Encoding</td>
            <td>文
            档的编码（Encode）方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的
            下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩，但只有Unix上的Netscape和Windows上的IE
            4、IE 5才支持它。因此，Servlet应该通过查看Accept-Encoding头（即request.getHeader("Accept-
            Encoding")）检查浏览器是否支持gzip，为支持gzip的浏览器返回经gzip压缩的HTML页面，为其他浏览器返回普通页面。</td>
        </tr>
        <tr>
            <td>Content-Length </td>
            <td>表
            示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势，可以把输出文档写入
            ByteArrayOutputStram，完成后查看其大小，然后把该值放入Content-Length头，最后通过
            byteArrayStream.writeTo(response.getOutputStream()发送内容。</td>
        </tr>
        <tr>
            <td>Content-Type</td>
            <td>表示后面的文档属于什么MIME类型。Servlet默认为text/plain，但通常需要显式地指定为text/html。由于经常要设置Content-Type，因此HttpServletResponse提供了一个专用的方法setContentTyep。 <br />
            </td>
        </tr>
        <tr>
            <td>Date </td>
            <td>当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。 </td>
        </tr>
        <tr>
            <td>Expires </td>
            <td>应该在什么时候认为文档已经过期，从而不再缓存它？</td>
        </tr>
        <tr>
            <td>Last-Modified</td>
            <td>文
            档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期，该请求将被视为一个条件GET，只有改动时间迟于指定时间的文档
            才会返回，否则返回一个304（Not Modified）状态。Last-Modified也可用setDateHeader方法来设置。</td>
        </tr>
        <tr>
            <td>Location </td>
            <td>表示客户应当到哪里去提取文档。Location通常不是直接设置的，而是通过HttpServletResponse的sendRedirect方法，该方法同时设置状态代码为302。 </td>
        </tr>
        <tr>
            <td>Refresh</td>
            <td>表示浏览器应该在多少时间之后刷新文档，以秒计。除了刷新当前文档之外，你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 <br />
            注
            意这种功能通常是通过设置HTML页面HEAD区的＜META HTTP-EQUIV="Refresh"
            CONTENT="5;URL=http://host/path"＞实现，这是因为，自动刷新或重定向对于那些不能使用CGI或Servlet的
            HTML编写者十分重要。但是，对于Servlet来说，直接设置Refresh头更加方便。 <br />
            <br />
            注意Refresh的意义是&#8220;N秒之后
            刷新本页面或访问指定页面&#8221;，而不是&#8220;每隔N秒刷新本页面或访问指定页面&#8221;。因此，连续刷新要求每次都发送一个Refresh头，而发送204状态代码则
            可以阻止浏览器继续刷新，不管是使用Refresh头还是＜META HTTP-EQUIV="Refresh" ...＞。 <br />
            <br />
            注意Refresh头不属于HTTP 1.1正式规范的一部分，而是一个扩展，但Netscape和IE都支持它。</td>
        </tr>
        <tr>
            <td>Server</td>
            <td>服务器名字。Servlet一般不设置这个值，而是由Web服务器自己设置。</td>
        </tr>
        <tr>
            <td>Set-Cookie </td>
            <td>设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...)，而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。</td>
        </tr>
        <tr>
            <td>WWW-Authenticate</td>
            <td>客
            户应该在Authorization头中提供什么类型的授权信息？在包含401（Unauthorized）状态行的应答中这个头是必需的。例如，
            response.setHeader("WWW-Authenticate", "BASIC realm=＼"executives＼"")。 <br />
            注意Servlet一般不进行这方面的处理，而是让Web服务器的专门机制来控制受密码保护页面的访问（例如.htaccess）。</td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/lukewange-hit1983/aggbug/228111.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lukewange-hit1983/" target="_blank">LukeW</a> 2008-09-10 12:05 <a href="http://www.blogjava.net/lukewange-hit1983/archive/2008/09/10/228111.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HTTP请求头信息</title><link>http://www.blogjava.net/lukewange-hit1983/archive/2008/08/20/223246.html</link><dc:creator>LukeW</dc:creator><author>LukeW</author><pubDate>Wed, 20 Aug 2008 05:58:00 GMT</pubDate><guid>http://www.blogjava.net/lukewange-hit1983/archive/2008/08/20/223246.html</guid><wfw:comment>http://www.blogjava.net/lukewange-hit1983/comments/223246.html</wfw:comment><comments>http://www.blogjava.net/lukewange-hit1983/archive/2008/08/20/223246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lukewange-hit1983/comments/commentRss/223246.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lukewange-hit1983/services/trackbacks/223246.html</trackback:ping><description><![CDATA[HTTP客户程序（例如浏览器），向服务器发送请求的时候必须指明请求类型（一般是GET或者POST）。如有必要，客户程序还可以选择发送其他的请求
头。大多数请求头并不是必需的，但Content-Length除外。对于POST请求来说Content-Length必须出现。<br />
<br />
下面是一些最常见的请求头：<br />
<br />
Accept：浏览器可接受的MIME类型。<br />
Accept-Charset：浏览器可接受的字符集。<br />
Accept-Encoding：浏览器能够进行解码的数据编码方式，比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间。<br />
Accept-Language：浏览器所希望的语言种类，当服务器能够提供一种以上的语言版本时要用到。<br />
Authorization：授权信息，通常出现在对服务器发送的WWW-Authenticate头的应答中。<br />
Connection：
表示是否需要持久连接。如果Servlet看到这里的值为&#8220;Keep-Alive&#8221;，或者看到请求使用的是HTTP 1.1（HTTP
1.1默认进行持久连接），它就可以利用持久连接的优点，当页面包含多个元素时（例如Applet，图片），显著地减少下载所需要的时间。要实现这一点，
Servlet需要在应答中发送一个Content-Length头，最简单的实现方法是：先把内容写入ByteArrayOutputStream，然
后在正式写出内容之前计算它的大小。<br />
Content-Length：表示请求消息正文的长度。<br />
Cookie：这是最重要的请求头信息之一，参见后面《Cookie处理》一章中的讨论。<br />
From：请求发送者的email地址，由一些特殊的Web客户程序使用，浏览器不会用到它。<br />
Host：初始URL中的主机和端口。<br />
If-Modified-Since：只有当所请求的内容在指定的日期之后又经过修改才返回它，否则返回304&#8220;Not Modified&#8221;应答。<br />
Pragma：指定&#8220;no-cache&#8221;值表示服务器必须返回一个刷新后的文档，即使它是代理服务器而且已经有了页面的本地拷贝。<br />
<div style="overflow: hidden; visibility: hidden; width: 1px; color: rgb(244, 251, 255); height: 1px;">JAVA手机网[www.cnjm.net]</div>
<p>Referer：包含一个URL，用户从该URL代表的页面出发访问当前请求的页面。<br />
User-Agent：浏览器类型，如果Servlet返回的内容与浏览器类型有关则该值非常有用。<br />
UA-Pixels，UA-Color，UA-OS，UA-CPU：由某些版本的IE浏览器所发送的非标准的请求头，表示屏幕大小、颜色深度、操作系统和CPU类型。<br />
有关HTTP头完整、详细的说明，请参见<a href="http://www.cnjm.net/resfetch/JiGbbGz0UF9f....4f-r4cT9j1-i.cRsxJzEIHxf" target="_blank">http://www.w3.org/Protocols/</a> 的HTTP规范。<br />
</p>
<p>java 读取方法</p>
<p>&nbsp; Enumeration headerNames = request.getHeaderNames();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(headerNames.hasMoreElements()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String headerName = (String)headerNames.nextElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.println("&lt;p&gt;"+headerName+"&nbsp; "+request.getHeader(headerName)+"&lt;/p&gt;");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
</p>
<img src ="http://www.blogjava.net/lukewange-hit1983/aggbug/223246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lukewange-hit1983/" target="_blank">LukeW</a> 2008-08-20 13:58 <a href="http://www.blogjava.net/lukewange-hit1983/archive/2008/08/20/223246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>