java-socket服务器给浏览器发信息(1).doc

上传人:j****9 文档编号:2268053 上传时间:2019-05-03 格式:DOC 页数:30 大小:315KB
下载 相关 举报
java-socket服务器给浏览器发信息(1).doc_第1页
第1页 / 共30页
java-socket服务器给浏览器发信息(1).doc_第2页
第2页 / 共30页
java-socket服务器给浏览器发信息(1).doc_第3页
第3页 / 共30页
java-socket服务器给浏览器发信息(1).doc_第4页
第4页 / 共30页
java-socket服务器给浏览器发信息(1).doc_第5页
第5页 / 共30页
点击查看更多>>
资源描述

1、Java Socket 现实简单的 HTTP 服务 一个简单的用 Java Socket 编写的 HTTP 服务器应用, 演示了请求和应答的协议通信内容以及给客户端返回 HTML 文本和二进制数据文件(一个图片), 同时展示了 404, 200 等状态码.首先运行这个程序,然后打开 Web 浏览器,键入 http:/localhost,则这个程序能够显示出浏览器发送了那些信息并且向浏览器返回一个网页和一副图片, 并测试同浏览器对话. 当浏览器看到 HTML 中带有图片地址时, 则会发出第二次连接来请求图片等资源. 这个例子可以帮您理解 Java 的 HTTP 服务器软件是基于 J2SE 的 S

2、ocket 等软件编写的概念, 并熟悉 HTTP 协议. 相反的用 Telnet 连接到已有的服务器则可以帮忙理解浏览器的运行过程和服务器端的返回内容. 当用户在 Web 浏览器地址栏中输入一个带有 http:/前缀的 URL 并按下 Enter后,或者在 Web 页面中某个以 http:/开头的超链接上单击鼠标,HTTP 事务处理的第一个阶段-建立连接阶段就开始了.HTTP 的默认端口是 80. 随着连接的建立,HTTP 就进入了客户向服务器发送请求的阶段.客户向服务器发送的请求是一个有特定格式的 ASCII 消息,其语法规则为: : Entity Body 请求消息的顶端是请求行,用于指定

3、方法,URL 和 HTTP 协议的版本,请求行的最后是回车换行.方法 GET,POST,HEAD,PUT,DELETE 等. 在请求行之后是若干个报头(Header)行.每个报头行都是由一个报头和一个取值构成的二元对,报头和取值之间以“:“分隔;报头行的最后是回车换行.常见的报头有 Accept(指定 MIME媒体类型),Accept_Charset(响应消息的编码方式),Accept_Encoding(响应消息的字符集),User_Agent(用户的浏览器信息)等. 在请求消息的报头行之后是一个回车换行,表明请求消息的报头部分结束.在这个之后是请求消息的消息实体(Entity Body).具

4、体的例子参看 httpRequest.txt. Web 服务器在收到客户请求并作出处理之后,要向客户发送应答消息.与请求消息一样,应答消息的语法规则为: : Entity Body 应答消息的第一行为状态行,其中包括了 HTTP 版本号,状态码和对状态码进行简短解释的消息;状态行的最后是回车换行.状态码由 3 位数字组成,有 5 类: 参看:HTTP 应答码及其意义 1XX 保留 2XX 表示成功 3XX 表示 URL 已经被移走 4XX 表示客户错误 5XX 表示服务器错误 例如:415,表示不支持改媒体类型;503,表示服务器不能访问.最常见的是 200,表示成功.常见的报头有:Last_

5、Modified(最后修改时间),Content_Type(消息内容的 MIME 类型),Content_Length(内容长度)等. 在报头行之后也是一个回车换行,用以表示应答消息的报头部分的结束,以及应答消息实体的开始. 下面是一个应答消息的例子: HTTP/1.0 200 OK Date: Moday,07-Apr-97 21:13:02 GMT Server:NCSA/1.1 MIME_Version:1.0 Content_Type:text/html Last_Modified:Thu Dec 5 09:28:01 1996 Coentent_Length:3107 在用 Java

6、 语言实现 HTTP 服务器时,首先启动一个 .ServerSocket 在提供服务的端口上监听连接.向客户返回文本时,可以用 PrintWriter,但是如果返回二进制数据,则必须使用 OutputStream.write(byte)方法,返回的应答消息字符串可以使用 String.getBytes()方法转换为字节数组返回,或者使用PrintStream 的 print()方法写入文本,用 write(byte)方法写入二进制数据.源程序来自 http:/ POST 请求时会阻塞,本程序解决了此问题,另外,本程序在原有的基础上增加了文件上传与下载模拟功能:Java 代码 import ja

7、va.io.File; import java.io.FileInputStream; 1. import java.io.IOException; 2. import java.io.InputStream; 3. import java.io.PrintStream; 4. import java.io.PrintWriter; 5. import .ServerSocket; 6. import .Socket; 7. import .URLDecoder; 8. import java.util.ArrayList; 9. import java.util.StringTokenize

8、r; 10. 11./* 12. * 13. * author 刘长炯 14. * modi by jzj 15. * 16. */ 17.public class SimpleHttpServer implements Runnable 18. 19. ServerSocket serverSocket;/服务器 Socket 20. 21. public static int PORT = 80;/标准 HTTP 端口 22. 23. public String encoding = “GBK“; 24. 25. public SimpleHttpServer() 26. try 27.

9、serverSocket = new ServerSocket(PORT); 28. catch (Exception e) 29. e.printStackTrace(); 30. System.exit(1); 31. new Thread(this).start(); System.out.println(“HTTP 服务器正在运行,端口:“ + PORT); 32. 33. 34. public void run() 35. while (true) 36. try 37. Socket client = serverSocket.accept();/客户机(这里是 IE 等浏览器)已

10、经连接到当前服务器 38. if (client != null) 39. System.out.println(“连接到服务器的用户:“ + client); 40. try 41. / 第一阶段: 打开输入流 42. InputStream is = client.getInputStream(); 43. 44. System.out.println(“客户端发送的请求信息:“); 45. / 读取第一行, 请求地址 46. String line = readLine(is, 0); 47. /打印请求行 48. System.out.print(line); 49. / 取的是 UR

11、L 部分 50.String resource = line.substring(line.indexOf(/), line.lastIndexOf(/) - 5); 51. /获得请求的资源的地址 52. resource = URLDecoder.decode(resource, encoding);/反编码 URL 地址 53. String method = new StringTokenizer(line).nextElement() 54. .toString();/ 获取请求方法, GET或者 POST 55. int contentLength = 0;/如果为 POST 方法

12、,则会有消息体长度 56. 57. / 读取所有浏览器发送过来的请求参数头部信息 58. do 59. line = readLine(is, 0); 60. /如果有 Content-Length 消息头时取出 61. if (line.startsWith(“Content-Length“) 62. contentLength = Integer.parseInt(line.split(“:“)1 63. .trim(); 64. 65. /打印请求部信息 66. System.out.print(line); 67. /如果遇到了一个单独的回车换行,则表示请求头结束 68. while

13、(!line.equals(“rn“); 69. /如果是 POST 请求,则有请求体 70. if (“POST“.equalsIgnoreCase(method) 71. /注,这里只是简单的处理表单提交的参数,而对于上传文件这里是不能这样处理的, 72. /因为上传的文件时消息体不只是一行,会有多行消息体 73. System.out.print(readLine(is, contentLength); 74. System.out.println(); 75. 76. 77. System.out.println(“客户端发送的请求信息结束 Hello Http Server“); 1

14、14. out.println(“你好, 这是一个Java HTTP 服务器 demo 应用.“); 115. out.println(“您请求的路径是:“ + resource + “); 116. out.println(“你请求的页面含有图片:“ 117. + “手动点击打开 test.gif 图片文件.“); 118. out.println(“服务器不支持 jpg格式图片,所以显示 XX:“ 119. + “ 120. + “手动点击打开 test.jpg,会跳转另一页面,并且服务返回为 404 错误“); 121. out 122. .println(“ POST 表单 “ 123

15、. + “ “ 124. + “); 125. out 126. .println(“GET 表单 “ 127. + “ “ 128. + “); 129. 130. out 131. .println(“ 133. + “文件上传“ 134. + “ “ 135. + “ 136. + “ “ 137. + “ “ 138. + “); 139. out.println(“点击此处模拟文件下载“); 140. 141. out.close(); 142. 143. closeSocket(client); 144. 145. catch (Exception e) 146. System.o

16、ut.println(“HTTP 服务器错误:“ + e.getLocalizedMessage(); 147. 148. 149. /System.out.println(client+“连接到 HTTP 服务器“);/如果加入这一句,服务器响应速度会很慢 150. catch (Exception e) 151. System.out.println(“HTTP 服务器错误:“ + e.getLocalizedMessage(); 152. 153. 154. 155. 156. /* 157. * 这里我们自己模拟读取一行,因为如果使用 API 中的BufferedReader 时,它是

17、读取到一个回车换行后 158. * 才返回,否则如果没有读取,则一直阻塞,这就导致如果为POST 请求时,表单中的元素会以消息体传送, 159. * 这时,消息体最末按标准是没有回车换行的,如果此时还使用BufferedReader 来读时,则 POST 提交 160. * 时会阻塞。如果是 POST 提交时我们按照消息体的长度Content-Length 来截取消息体,这样就不会阻塞 161. */ 162. private String readLine(InputStream is, int contentLe) throws IOException 163. ArrayList lin

18、eByteList = new ArrayList(); 164. byte readByte; 165. int total = 0; 166. if (contentLe != 0) 167. do 168. readByte = (byte) is.read(); 169. lineByteList.add(Byte.valueOf(readByte); 170. total+; 171. while (total contentLe);/消息体读还未读完 172. else 173. do 174. readByte = (byte) is.read(); 175. lineByteL

19、ist.add(Byte.valueOf(readByte); 176. while (readByte != 10); 177. 178. 179. byte tmpByteArr = new bytelineByteList.size(); 180. for (int i = 0; i lineByteList.size(); i+) 181. tmpByteArri = (Byte) lineByteList.get(i).byteValue(); 182. 183. lineByteList.clear(); 184. 185. String tmpStr = new String(t

20、mpByteArr, encoding); 186. /* http 请求的 header 中有一个 Referer 属性,这个属性的意思就是如果当前请求是从别的页面链接过 187. * 来的,那个属性就是那个页面的 url,如果请求的 url 是直接从浏览器地址栏输入的就没有这个值。得 188. * 到这个值可以实现很多有用的功能,例如防盗链,记录访问来源以及记住刚才访问的链接等。另外,浏 189. * 览器发送这个 Referer 链接时好像固定用 UTF-8 编码的,所以在 GBK 下出现乱码,我们在这里纠正一下 190. */ 191. if (tmpStr.startsWith(“R

21、eferer“) /如果有 Referer 头时,使用 UTF-8 编码 192. tmpStr = new String(tmpByteArr, “UTF-8“); 193. 194. return tmpStr; 195. 196. 197. /* 198. * 关闭客户端 socket 并打印一条调试信息. 199. * param socket 客户端 socket. 200. */ 201. void closeSocket(Socket socket) 202. try 203. socket.close(); 204. catch (IOException ex) 205. ex

22、.printStackTrace(); 206. 207. System.out.println(socket + “离开了 HTTP 服务器“); 208. 209. 210. /* 211. * 读取一个图像文件的内容并返回给浏览器端. 212. * param fileName 文件名 213. * param socket 客户端 socket. 214. */ 215. void imgDownload(String fileName, Socket socket) 216. 217. try 218. PrintStream out = new PrintStream(socket

23、.getOutputStream(), true); 219. File fileToSend = new File(fileName); 220. if (fileToSend.exists() /返回应答消息,并结束应答 222. out.println(“Content-Type: application/octet-stream“); 223. out.println(“Content-Length: “ + fileToSend.length();/ 返回内容字节数 224. out.println();/ 根据 HTTP 协议, 空行将结束头信息 225. 226. FileInp

24、utStream fis = new FileInputStream(fileToSend); 227. byte data = new bytefis.available(); 228. fis.read(data); 229. out.write(data); 230. /文件下载完后关闭 socket 流,但 socket 还没有关闭 231. out.close(); 232. fis.close(); 233. 234. catch (Exception e) 235. e.printStackTrace(); 236. 237. 238. 239. /* 240. * 读取一个文件

25、的内容并返回给浏览器端. 241. * param fileName 文件名 242. * param socket 客户端 socket. 243. */ 244. void fileDownload(String fileName, Socket socket) 245. try 246. PrintStream out = new PrintStream(socket.getOutputStream(), true); 247. File fileToSend = new File(fileName); 248. if (fileToSend.exists() /返回应答消息,并结束应答

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 实用文档资料库 > 策划方案

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。