⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter24.htm

📁 这是一个学写JAVA的好东西
💻 HTM
📖 第 1 页 / 共 3 页
字号:
	<TR> 		<TD colspan="2" align=middle>			<BR>			<div style="FONT-SIZE: 18pt; COLOR: #990000; FONT-FAMILY: 楷体_GB2312" align=center><B>网络协议</b></div><br><div style="COLOR: #990000; font-family: ; font-size: 18px;宋体;" align=center>用Socket类实现HTTP协议客户端应用</div>			<DIV style="PADDING-RIGHT: 10px; PADDING-LEFT: 10px; FONT-SIZE: 10.5pt; COLOR: black; LINE-HEIGHT: 180%" align=left>                         <br>&nbsp;&nbsp;&nbsp;&nbsp;<P>Http客户端程序已集成在Java语言中,可以通过URLConnection类调用。遗憾的是,由于SUN没有公布Http客户程序的源码,它实现的细节仍是一个谜。本文根据HTTP协议规范,用Java.net.Socket类实现一个HTTP协议客户端程序。 </P>
<P>  1.Socket类:<BR><BR>  了解TCP/IP协议集通信的读者知道,协议间的通信是通过Socket完成的。在Java.net包中,Socket类就是对Socket的具体实现。它通过连接到主机后,返回一个I/O流,实现协议间的信息交换。</P>
<P>  2 . HTTP协议<BR><BR>  HTTP协议同其它TCP/IP协议集中的协议一样,是遵循客户/服务器模型工作的。客户端发往服务端的信息格式如下:<BR><BR>请求方法 URL HTTP协议的版本号<BR>提交的元信息<BR>**空行**<BR>实体<BR><BR>  请求方法是对这次连接工作的说明,目前HTTP协议已经发展到1.1版,它包括GET、HEAD、POST、DELETE、OPTIONS、TRACE、PUT七种。元信息是关于当前请求的信息。通过分析元信息,可以检查实体数据是否完整,接收过程是否出错,类型是否匹配等。元信息的引入使HTTP协议通信更加稳妥可靠。实体是请求的具体内容。<BR><BR>  将上述报文发往Web服务器,如果成功,应答格式如下:<BR><BR>HTTP协议的版本号 应答状态码 应答状态码说明<BR>接收的元信息<BR>**空行**<BR>实体<BR><BR>  以上报文发向客户端,并且接收成功,彼此间关闭连接,完成一次握手。下面用最常用的GET方法,来说明具体的报文应用:<BR></P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>GET http://www.youhost.com HTTP/1.0<BR>accept: www/source; text/html; image/gif; image/jpeg; */*<BR>User_Agent: myAgent<BR>**空行**</TD></TR></TBODY></TABLE>
<P>  这个报文是向www.youhost.com主机请求一个缺省HTML文档。客户端HTTP协议版本号是1.0版,元信息包括可接收的文件格式,用户代理,每一段之间用回车换行符分隔,最后以一个空行结束。发向服务器后,如果执行过程正常,服务器返回以下代码:<BR><BR>HTTP/1.1 200 OK<BR>Date: Tue, 14 Sep 1999 02:19:57 GMT<BR>Server: Apache/1.2.6<BR>Connection: close<BR>Content-Type: text/html<BR>**空行**<BR><html><head>...</head><body>...</body></html><BR><BR>  HTTP/1.1表示这个HTTP服务器是1.1版,200是服务器对客户请求的应答状态码,OK是对应答状态码的解释,之后是这个文档的元信息和文档正文。(相关应答状态码和元信息的解释请参阅Inetrnet标准草案:RFC2616)。</P>
<P>  3. HTTP客户端程序:</P>
<TABLE cellPadding=0 width="100%" bgColor=#ffffff border=0>
<TBODY>
<TR>
<TD>
<P>import java.net.*;<BR>import java.io.*;<BR>import java.util.Properties;<BR>import java.util.Enumeration;<BR>public class Http {<BR>protected Socket client;<BR>protected BufferedOutputStream sender;<BR>protected BufferedInputStream receiver;<BR>protected ByteArrayInputStream byteStream;<BR>protected URL target;<BR>private int responseCode=-1;<BR>private String responseMessage="";<BR>private String serverVersion="";<BR>private Properties header = new Properties();<BR>public Http() { }<BR>public Http(String url) {<BR>GET(url) ;<BR>}<BR>/* GET方法根据URL,会请求文件、数据库查询结果、程序运行结果等多种内容 */<BR>public void GET(String url) {<BR>try {<BR>checkHTTP(url);<BR>openServer(target.getHost(),target.getPort() );<BR>String cmd = "GET "+ getURLFormat(target) +" HTTP/1.0\r\n"<BR>+ getBaseHeads()+"\r\n";<BR>sendMessage(cmd);<BR>receiveMessage();<BR>}catch(ProtocolException p) {<BR>p.printStackTrace();<BR>return;<BR>}catch(UnknownHostException e) {<BR>e.printStackTrace();<BR>return;<BR>}catch(IOException i)</P>
<P>i.printStackTrace();<BR>return;<BR>}<BR>}</P>
<P>/*<BR>* HEAD方法只请求URL的元信息,不包括URL本身。若怀疑本机和服务器上的<BR>* 文件相同,用这个方法检查最快捷有效。<BR>*/<BR>public void HEAD(String url) {<BR>try {<BR>checkHTTP(url);<BR>openServer(target.getHost(),target.getPort() );<BR>String cmd = "HEAD "+getURLFormat(target)+" HTTP/1.0\r\n"<BR>+getBaseHeads()+"\r\n";<BR>sendMessage(cmd);<BR>receiveMessage();<BR>}catch(ProtocolException p) {<BR>p.printStackTrace();<BR>return;<BR>}catch(UnknownHostException e) {<BR>e.printStackTrace();<BR>return;<BR>}catch(IOException i)</P>
<P>i.printStackTrace();<BR>return;<BR>}<BR>}<BR>/*<BR>* POST方法是向服务器传送数据,以便服务器做出相应的处理。例如网页上常用的<BR>* 提交表格。<BR>*/<BR>public void POST(String url,String content) {<BR>try {<BR>checkHTTP(url);<BR>openServer(target.getHost(),target.getPort() );<BR>String cmd = "POST "+ getURLFormat(target) +"<BR>HTTP/1.0\r\n"+getBaseHeads();<BR>cmd += "Content-type: application/x-www-form-urlencoded\r\n";<BR>cmd += "Content-length: " + content.length() + "\r\n\r\n";<BR>cmd += content+"\r\n";<BR>sendMessage(cmd);<BR>receiveMessage();<BR>}catch(ProtocolException p) {<BR>p.printStackTrace();<BR>return;<BR>}catch(UnknownHostException e) {<BR>e.printStackTrace();<BR>return;<BR>}catch(IOException i)</P>
<P>i.printStackTrace();<BR>return;<BR>}</P>
<P>}<BR>protected void checkHTTP(String url) throws ProtocolException {<BR>try {<BR>URL target = new URL(url);<BR>if(target==null || !target.getProtocol().toUpperCase().equals("HTTP") )<BR>throw new ProtocolException("这不是HTTP协议");<BR>this.target = target;<BR>}catch(MalformedURLException m) {<BR>throw new ProtocolException("协议格式错误");<BR>}<BR>}<BR>/*<BR>* 与Web服务器连接。若找不到Web服务器,InetAddress会引发UnknownHostException<BR>* 异常。若Socket连接失败,会引发IOException异常。<BR>*/<BR>protected void openServer(String host,int port) throws<BR>UnknownHostException,IOException {<BR>header.clear();<BR>responseMessage=""; responseCode=-1;<BR>try {<BR>if(client!=null) closeServer();<BR>if(byteStream != null) {<BR>byteStream.close(); byteStream=null;<BR>}<BR>InetAddress address = InetAddress.getByName(host);<BR>client = new Socket(address,port==-1?80:port);<BR>sender = new BufferedOutputStream(client.getOutputStream());<BR>receiver = new BufferedInputStream(client.getInputStream());<BR>}catch(UnknownHostException u) {<BR>throw u;<BR>}catch(IOException i) {<BR>throw i;<BR>}<BR>}<BR>/* 关闭与Web服务器的连接 */<BR>protected void closeServer() throws IOException {<BR>if(client==null) return;<BR>try {<BR>client.close(); sender.close(); receiver.close();<BR>}catch(IOException i) {<BR>throw i;<BR>}<BR>client=null; sender=null; receiver=null;<BR>}<BR>protected String getURLFormat(URL target) {<BR>String spec = "http://"+target.getHost();<BR>if(target.getPort()!=-1)<BR>spec+=":"+target.getPort();<BR>return spec+=target.getFile();<BR>}</P>
<P>/* 向Web服务器传送数据 */<BR>protected void sendMessage(String data) throws IOException{<BR>sender.write(data.getBytes(),0,data.length());<BR>sender.flush();<BR>}<BR>/* 接收来自Web服务器的数据 */<BR>protected void receiveMessage() throws IOException{<BR>byte data[] = new byte[1024];<BR>int count=0;<BR>int word=-1;<BR>// 解析第一行<BR>while( (word=receiver.read())!=-1 ) {<BR>if(word=='\r'||word=='\n') {<BR>word=receiver.read();<BR>if(word=='\n') word=receiver.read();<BR>break;<BR>}<BR>if(count == data.length) data = addCapacity(data);<BR>data[count++]=(byte)word;<BR>}<BR>String message = new String(data,0,count);<BR>int mark = message.indexOf(32);<BR>serverVersion = message.substring(0,mark);<BR>while( mark&lt;message.length() &amp;&amp; message.charAt(mark+1)==32 ) mark++;<BR>responseCode = Integer.parseInt(message.substring(mark+1,mark+=4));<BR>responseMessage = message.substring(mark,message.length()).trim();</P>
<P>// 应答状态码和处理请读者添加<BR>switch(responseCode) {<BR>case 400:<BR>throw new IOException("错误请求");<BR>case 404:<BR>throw new FileNotFoundException( getURLFormat(target) );<BR>case 503:<BR>throw new IOException("服务器不可用" );<BR>}<BR>if(word==-1) throw new ProtocolException("信息接收异常终止");<BR>int symbol=-1;<BR>count=0;<BR>// 解析元信息<BR>while( word!='\r' &amp;&amp; word!='\n' &amp;&amp; word&gt;-1) {<BR>if(word=='\t') word=32;<BR>if(count==data.length) data = addCapacity(data);<BR>data[count++] = (byte)word;<BR>parseLine: {<BR>while( (symbol=receiver.read()) &gt;-1 ) {<BR>switch(symbol) {<BR>case '\t':<BR>symbol=32; break;<BR>case '\r':<BR>case '\n':<BR>word = receiver.read();<BR>if( symbol=='\r' &amp;&amp; word=='\n') {<BR>word=receiver.read();<BR>if(word=='\r') word=receiver.read();<BR>}<BR>if( word=='\r' || word=='\n' || word&gt;32) break parseLine;<BR>symbol=32; break;<BR>}<BR>if(count==data.length) data = addCapacity(data);<BR>data[count++] = (byte)symbol;<BR>}<BR>word=-1;<BR>}<BR>message = new String(data,0,count);<BR>mark = message.indexOf(':');<BR>String key = null;<BR>if(mark&gt;0) key = message.substring(0,mark);<BR>mark++;<BR>while( mark&lt;message.length() &amp;&amp; message.charAt(mark)&lt;=32 ) mark++;<BR>String value = message.substring(mark,message.length() );<BR>header.put(key,value);<BR>count=0;<BR>}<BR>// 获得正文数据<BR>while( (word=receiver.read())!=-1) {<BR>if(count == data.length) data = addCapacity(data);<BR>data[count++] = (byte)word;<BR>}<BR>if(count&gt;0) byteStream = new ByteArrayInputStream(data,0,count);<BR>data=null;<BR>closeServer();<BR>}<BR>public String getResponseMessage() {<BR>return responseMessage;<BR>}<BR>public int getResponseCode() {<BR>return responseCode;<BR>}<BR>public String getServerVersion() {<BR>return serverVersion;<BR>}<BR>public InputStream getInputStream() {<BR>return byteStream;<BR>}<BR>public synchronized String getHeaderKey(int i) {<BR>if(i&gt;=header.size()) return null;<BR>Enumeration enum = header.propertyNames();<BR>String key = null;<BR>for(int j=0; j&lt;=i; j++)<BR>key = (String)enum.nextElement();<BR>return key;<BR>}<BR>public synchronized String getHeaderValue(int i) {<BR>if(i&gt;=header.size()) return null;<BR>return header.getProperty(getHeaderKey(i));<BR>}<BR>public synchronized String getHeaderValue(String key) {<BR>return header.getProperty(key);<BR>}<BR>protected String getBaseHeads() {<BR>String inf = "User-Agent: myselfHttp/1.0\r\n"+<BR>"Accept: www/source; text/html; image/gif; */*\r\n";<BR>return inf;<BR>}<BR>private byte[] addCapacity(byte rece[]){<BR>byte temp[] = new byte[rece.length+1024];<BR>System.arraycopy(rece,0,temp,0,rece.length);<BR>return temp;<BR>}<BR>}</P></TD></TR></TBODY></TABLE>
<P>  注: 程序中只实现GET、HEAD、POST三种方法。其他几种因不常使用,暂且忽略。</P><br><br>          </DIV>		</TD>	</TR>	<TR> 		<TD class=center01>			<div align="center">来源:天极网 作者:<div>		</TD>		<TD width="280" class=center01>			<div align="center">			<font color=#0000FF><a href='chapter.php?id=387&volume=2&chapter=10'>上一页</a></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;			<font color=#0000FF><a href="serialize.php?id=387">回书目</a></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;			<font color=#0000FF><a href='chapter.php?id=387&volume=2&chapter=12'>下一页</a></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;			</div>		</TD>	</TR>	</TBODY></TABLE><table><tr><td width="760"> <table width="760" height="10" border="0" cellpadding="0" cellspacing="0">                        <tr>                                <td></td>                        </tr>                </table>                <!------------ 评论 ---------------->                <table width="760" border="0" cellpadding="0" cellspacing="0">                        <tr>                                <td><iframe width="100%" id=vs frameborder=0 scrolling=no src="comment_list1.php?id=387"></iframe>                                </td>                        </tr>                </table><br><script language=javascript>function CheckNetwordForm(theForm){        if("" == theForm.content.value)        {                alert("写两句吧~~");                theForm.content.focus();                return false;        }        var index;        for(index=0;index<theForm.content.value.length;index++)        {                if(" " != theForm.content.value.charAt(index))                        break;        }        if(index == theForm.content.value.length) {                alert("写两句吧~~");                theForm.content.focus();                return false;        }        if (theForm.content.value.length>100){                alert("评论字数不能超过100哦");                theForm.content.focus();                return false;        }        return true;}</script>                <!------------------ 评论 --------------->                <form name=netword method=post action="insertnetword.php" onsubmit="javascript: return CheckNetwordForm(this);">                <table width="760" border="0" cellpadding="0" cellspacing="0">                        <tr>                                <td height="25" class="text6">&nbsp;给此书打分:<a name="1"></a>                                        <select name="score">                                                <option value=5 selected>非常好</option>                                                <option value=4>还凑合</option>                                                <option value=3>一般吧</option>                                                <option value=2>不太行</option>                                                <option value=1>太差了</option>                                        </select> &nbsp; 用户名:                                        <input name="id" value=387 type="hidden" id="id">                                        <input name="backurl" value=/book/chapter.php?id=387&volume=2&chapter=11 type="hidden">                                        <input name="username" type="text" id="username" size="20" maxlength="20">                                        <font color="#666666">*评论字数请控制在一百字以内</font> </td>                        </tr>                </table>                <br>&nbsp;<textarea name="content" cols="80" rows="4" wrap="OFF" id="description"></textarea>                <input type="submit" name="Submit" value="提交">                </form>        </td> </tr></table></td></tr></table> <TABLE cellSpacing=0 cellPadding=0 width=760 border=0>  <TBODY>    <TR>       <TD width="1003" height=9 background=images/t_bj01.gif><IMG height=1     src="images/ccc.gif" width=1></TD>    </TR>  </TBODY></TABLE><TABLE cellSpacing=0 cellPadding=0 width=760 bgColor=#ffffff border=0>  <TBODY>    <TR>       <TD><HR width=760 noShade SIZE=1> </TD>    </TR>    <TR>       <TD align=middle><A class=black href="http://www.chinaren.com/"     target=_blank>ChinaRen</A> - <A class=black     href="http://big5.www.sohu.com/" target=_blank>繁体版</A> - <A class=black     href="http://hr.sohu.com/hrm.html" target=_blank>搜狐招聘</A> - <A class=black     href="http://add.sohu.com/" target=_blank>网站登录</A> - <A class=black     href="http://help.sohu.com/" target=_blank>帮助中心</A> - <A class=black     href="http://book.news.sohu.com/onClick=this.style.behavior='url(#default#homepage)';this.setHomePage('http://www.sohu.com');return"     target=_blank false;>设置首页</A> - <A class=black     href="http://adinfo.sohu.com/" target=_blank>广告服务</A> - <A class=black     href="http://www.sohu.com/about/lianxi.htm" target=_blank>联系方式</A> - <A     class=black href="http://www.sohu.com/about/privacy.html"     target=_blank>保护隐私权</A> - <A class=black href="http://www.sohu.com/about/"     target=_blank>About SOHU</A> - <A class=black     href="http://www.sohu.com/about/" target=_blank>公司介绍</A><BR> <SPAN     class=eng>Copyright &copy; 2004 Sohu.com Inc. All rights reserved. 搜狐公司         版权所有</SPAN> </TD>    </TR>  </TBODY></TABLE></center></body></html><script language="JavaScript" src="http://nielsen.js.sohu.com/nnselect.js"></script><noscript><img src='http://ping.nnselect.com/ping.gif?c=119' height='1' width='1'></noscript>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -