javasocket服务器给浏览器发信息1.docx
《javasocket服务器给浏览器发信息1.docx》由会员分享,可在线阅读,更多相关《javasocket服务器给浏览器发信息1.docx(38页珍藏版)》请在冰豆网上搜索。
javasocket服务器给浏览器发信息1
JavaSocket现实简单的HTTP服务
一个简单的用JavaSocket编写的HTTP服务器应用,演示了请求和应答的协议通信内容以及给客户端返回HTML文本和二进制数据文件(一个图片),同时展示了404,200等状态码.
首先运行这个程序,然后打开Web浏览器,键入,则这个程序能够显示出浏览器发送了那些信息并且向浏览器返回一个网页和一副图片,并测试同浏览器对话. 当浏览器看到HTML中带有图片地址时,则会发出第二次连接来请求图片等资源. 这个例子可以帮您理解Java的HTTP服务器软件是基于J2SE的Socket等软件编写的概念,并熟悉HTTP协议. 相反的用Telnet连接到已有的服务器则可以帮忙理解浏览器的运行过程和服务器端的返回内容.
当用户在Web浏览器地址栏中输入一个带有,或者在Web页面中某个以,HTTP事务处理的第一个阶段--建立连接阶段就开始了.HTTP的默认端口是80. 随着连接的建立,HTTP就进入了客户向服务器发送请求的阶段.客户向服务器发送的请求是一个有特定格式的ASCII消息,其语法规则为:
<\r\n>
{
<\r\n>}
<\r\n>
{EntityBody}
请求消息的顶端是请求行,用于指定方法,URL和HTTP协议的版本,请求行的最后是回车换行.方法GET,POST,HEAD,PUT,DELETE等. 在请求行之后是若干个报头(Header)行.每个报头行都是由一个报头和一个取值构成的二元对,报头和取值之间以":
"分隔;报头行的最后是回车换行.常见的报头有Accept(指定MIME媒体类型),Accept_Charset(响应消息的编码方式),Accept_Encoding(响应消息的字符集),User_Agent(用户的浏览器信息)等. 在请求消息的报头行之后是一个回车换行,表明请求消息的报头部分结束.在这个之后是请求消息的消息实体(EntityBody).具体的例子参看httpRequest.txt.
Web服务器在收到客户请求并作出处理之后,要向客户发送应答消息.与请求消息一样,应答消息的语法规则为:
[]<\r\n>
{
<\r\n>}
<\r\n>
{EntityBody}
应答消息的第一行为状态行,其中包括了HTTP版本号,状态码和对状态码进行简短解释的消息;状态行的最后是回车换行.状态码由3位数字组成,有5类:
参看:
HTTP应答码及其意义
1XX保留
2XX表示成功
3XX表示URL已经被移走
4XX表示客户错误
5XX表示服务器错误
例如:
415,表示不支持改媒体类型;503,表示服务器不能访问.最常见的是200,表示成功.常见的报头有:
Last_Modified(最后修改时间),Content_Type(消息内容的MIME类型),Content_Length(内容长度)等.
在报头行之后也是一个回车换行,用以表示应答消息的报头部分的结束,以及应答消息实体的开始.
下面是一个应答消息的例子:
HTTP/1.0200OK
Date:
Moday,07-Apr-9721:
13:
02GMT
Server:
NCSA/1.1
MIME_Version:
1.0
Content_Type:
text/html
Last_Modified:
ThuDec509:
28:
011996
Coentent_Length:
3107
在用Java语言实现HTTP服务器时,首先启动一个,可以用PrintWriter,但是如果返回二进制数据,则必须使用OutputStream.write(byte[])方法,返回的应答消息字符串可以使用String.getBytes()方法转换为字节数组返回,或者使用PrintStream的print()方法写入文本,用write(byte[])方法写入二进制数据.
源程序来自_java,本程序是在原有基础上进行了一些调整,源程序在POST请求时会阻塞,本程序解决了此问题,另外,本程序在原有的基础上增加了文件上传与下载模拟功能:
Java代码
import ;
import ;
1.import ;
2.import ;
3.import ;
4.import ;
5.import ;
6.import ;
7.import ;
8.import ;
9.import ;
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. serverSocket = new ServerSocket(PORT);
28. } catch (Exception e) {
29. e.printStackTrace();
30. System.exit
(1);
31. }
new Thread(this).start();
"HTTP服务器正在运行,端口:
" + PORT);
32. }
33.
34. public void run() {
35. while (true) {
36. try {
37. Socket client = serverSocket.accept();//客户机(这里是 IE 等浏览器)已经连接到当前服务器
38. if (client !
= null) {
39. "连接到服务器的用户:
" + client);
40. try {
41. // 第一阶段:
打开输入流
42. InputStream is = client.getInputStream();
43.
44. "客户端发送的请求信息:
>>>>>>>>>>>>>>>>>>>>>>>>>");
45. // 读取第一行, 请求地址
46. String line = readLine(is, 0);
47. //打印请求行
48. ;
49. // < Method > < URL > < HTTP Version > <\r\n> 取的是URL部分
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方法,则会有消息体长度
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. ;
67. //如果遇到了一个单独的回车换行,则表示请求头结束
68. } while (!
line.equals("\r\n"));
69. //如果是POST请求,则有请求体
70. if ("POST".equalsIgnoreCase(method)) {
71. //注,这里只是简单的处理表单提交的参数,而对于上传文件这里是不能这样处理的,
72. //因为上传的文件时消息体不只是一行,会有多行消息体
73. , contentLength));
74. ;
75. }
76.
77. "客户端发送的请求信息结束 <<<<<<<<<<<<<<<<<<<<<<<<<<");
78. "用户请求的资源是:
" + resource);
79. "请求的类型是:
" + method);
80. ;
81.
82. //如果是下载文件
83. if (resource.startsWith("/download")) {
84. fileDownload("test.txt", client);
85. closeSocket(client);
86. continue;
87. }
88.
89. // GIF 图片就读取一个真实的图片数据并返回给客户端
90. if (resource.endsWith(".gif")) {
91. imgDownload("test.gif", client);
92. closeSocket(client);
93. continue;
94. }
95.
96. // 请求 JPG 格式就报错 404
97. if (resource.endsWith(".jpg")) {
98. PrintWriter out = new PrintWriter(client.getOutputStream(),
99. true);
100. out.println("HTTP/1.0 404 Not found");//返回应答消息,并结束应答
101. out.println();// 根据 HTTP 协议, 空行将结束头信息
102. out.close();
103. closeSocket(client);
104. continue;
105. } else {
106. // 用 writer 对客户端 socket 输出一段 HTML 代码
107. PrintWriter out = new PrintWriter(client.getOutputStream(),
108. true);
109. out.println("HTTP/1.0 200 OK");//返回应答消息,并结束应答
110. out.println("Content-Type:
text/html;charset=" + encoding);
111. out.println();// 根据 HTTP 协议, 空行将结束头信息
112.
113. out.println("
Hello Http Server
"); 114. 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("
"); 125. out
126. .println("
"); 129.
130. out
131. .println("
"); 139. out.println("点击此处模拟文件下载");
140.
141. out.close();
142.
143. closeSocket(client);
144. }
145. } catch (Exception e) {
146. "HTTP服务器错误:
" + e.getLocalizedMessage());
147. }
1