Cyh的博客
Email:kissyan4916@163.com
posts - 26, comments - 19, trackbacks - 0, articles - 220
導航
BlogJava
首頁
新隨筆
聯系
聚合
管理
公告
一直努力努力努力,像奴隸奴隸奴隸!~~
<
2025年7月
>
日
一
二
三
四
五
六
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
常用鏈接
我的隨筆
我的文章
我的評論
我的參與
最新評論
隨筆檔案
(25)
2011年5月 (1)
2010年4月 (12)
2010年1月 (1)
2009年12月 (2)
2009年6月 (1)
2009年4月 (4)
2009年2月 (4)
文章分類
(219)
Android(26)
DB(5)
J2EE(31)
J2SE(79)
JavaScript(15)
others(47)
SOA&Web Service(1)
中間件(1)
軟件工程(12)
軟件架構(2)
文章檔案
(220)
2011年8月 (1)
2010年12月 (23)
2010年11月 (2)
2010年8月 (5)
2010年7月 (2)
2010年6月 (2)
2010年5月 (1)
2010年4月 (12)
2010年3月 (28)
2010年2月 (5)
2010年1月 (23)
2009年12月 (39)
2009年6月 (14)
2009年5月 (31)
2009年3月 (2)
2009年2月 (29)
2009年1月 (1)
新聞檔案
(66)
2010年10月 (1)
2010年9月 (5)
2010年8月 (11)
2010年7月 (21)
2010年6月 (13)
2010年5月 (8)
2010年4月 (5)
2009年11月 (2)
相冊
Ryan
收藏夾
(7)
JAVA(7)
最新隨筆
1.?集成FCKeditor 3.5.3
2.?android自適應屏幕方向和大小
3.?Android游戲開發之旅(二十) 雙按事件捕獲
4.?Android游戲開發之旅(十八) SoundPool類
5.?Android游戲開發之旅(十九) 分辨率大全
6.?Android游戲開發之旅(十七) 圖像漸變特效
7.?Android游戲開發之旅(十六) 異步音樂播放
8.? Android游戲開發之旅(十四) 游戲開發實戰一
9.?Android游戲開發之旅(十五) 按鍵中斷處理
10.?Android游戲開發之旅(十二)Sensor重力感應(2)
搜索
最新評論
1.?re: struts2 checkboxlist標簽的使用
同居同意同意
--yuk
2.?re: struts2 checkboxlist標簽的使用
ss
--d
3.?re: JavaMail(4)--使用POP3接收郵件
郵件信息可以打印出來,可是下載郵件會出錯是什么原因?
--琳喵喵0721
4.?re: JavaMail(4)--使用POP3接收郵件
評論內容較長,點擊標題查看
--流風
5.?re: 操作PDF文件
評論內容較長,點擊標題查看
--ly.wolf
閱讀排行榜
1.?struts2 checkboxlist標簽的使用(18242)
2.?struts2異常攔截器(5868)
3.?struts2迭代標簽(3852)
4.?用freemind 秒殺Spring Security(1925)
5.?加載順序會影響對spring bean 的調用。(1494)
網絡編程>>HTTP服務器
Posted on 2009-12-12 16:22
啥都寫點
閱讀(334)
評論(0)
編輯
收藏
所屬分類:
J2SE
與一般的Socket編程一樣,服務器端需要在某個端口上開啟一個ServerSocket,以等待、接受客戶端的請求。
采用多線程技術,支持多用戶同時訪問,對于每一個請求,都用一個線程專門去處理。
客戶端發送給服務器端的HTTP請求遵循一定的格式,服務器端需要根據HTTP請求確定請求的類型以及請求的文件名,這些信息都存儲在請求消息的第一行中。比如,用戶瀏覽器地址欄中輸入:"
http://localhost:80/test/hehe.htm
",那么產生的請求的第一行便是"GET/test/hehe.htm HTTP/1.1"
Socket的getInetAddress方法能獲得客戶端的網絡地址信息,包括IP和端口號。
在給客戶端發送響應消息時,也要按照HTTP協議,給響應消息添加頭信息,然后將被請求文件的字節數組添加到頭信息的后面,頭信息的第一行為為"HTTP/1.1 200 0K" 表示"HTTP協議的版本為1.1,處理請求成功",頭信息的第一行為"HTTP/1.1 400"表示"HTTP協議的版本為1.1,處理請求失敗,文件沒找到"。
/** */
/**
* HTTP的服務器,接收來自客戶端的HTTP請求。
* 將要發布的HTML文件放置在工程的根目錄下,
* 然后在瀏覽器中輸入類似"
http://localhost
:80/"的網址,
* 將能夠顯示網頁的內容。
*/
public
class
HttpServer
{
//
服務器名和端口
String serverName;
int
serverPort;
//
定義server的名字、版本號、端口
public
HttpServer(String name,
int
port)
{
this
.serverName
=
name;
this
.serverPort
=
port;
}
public
void
run()
{
//
顯示名字和端口號
System.out.println(
"
HttpServer:
"
+
serverName
+
"
:
"
+
serverPort);
try
{
//
得到服務器監聽端口
ServerSocket server
=
new
ServerSocket(serverPort);
do
{
//
等待連接請求
Socket client
=
server.accept();
//
為連接請求分配一個線程
(
new
HTTPServerThread(client)).start();
}
while
(
true
);
}
catch
(Exception e)
{
e.printStackTrace();
System.exit(
1
);
}
}
//
構造一個server,并運行
public
static
void
main(String args[])
{
HttpServer server
=
new
HttpServer(
"
MyHTTPServer
"
,
80
);
server.run();
}
}
/** */
/**
* 處理HTTP請求的線程,一個HTTP請求對應一個線程
*/
class
HTTPServerThread
extends
Thread
{
//
服務器與客戶端之間的socket
Socket client;
public
HTTPServerThread(Socket client)
{
this
.client
=
client;
}
public
void
run()
{
try
{
//
顯示連接信息
describeConnectionInfo(client);
//
獲取流向到客戶端的輸出流
BufferedOutputStream outStream
=
new
BufferedOutputStream(client
.getOutputStream());
//
獲取來自客戶端的輸入流
HTTPInputStream inStream
=
new
HTTPInputStream(client
.getInputStream());
//
得到客戶端的請求頭(自定義類)
HTTPRequest request
=
inStream.getRequest();
//
顯示頭信息
request.log();
//
目前只處理GET請求
if
(request.isGetRequest())
{
processGetRequest(request, outStream);
}
System.out.println(
"
Request completed. Closing connection.
"
);
//
關閉socket
client.close();
}
catch
(IOException e)
{
System.out.println(
"
IOException occurred .
"
);
e.printStackTrace();
}
}
//
顯示socket連接信息
void
describeConnectionInfo(Socket client)
{
//
客戶端的主機名
String destName
=
client.getInetAddress().getHostName();
//
客戶端的IP地址
String destAddr
=
client.getInetAddress().getHostAddress();
//
客戶端的端口
int
destPort
=
client.getPort();
//
打印信息,表示客戶端已經連接到本服務器上
System.out.println(
"
Accepted connection to
"
+
destName
+
"
(
"
+
destAddr
+
"
)
"
+
"
on port
"
+
destPort
+
"
.
"
);
}
//
處理GET請求
void
processGetRequest(HTTPRequest request, BufferedOutputStream outStream)
throws
IOException
{
//
獲得客戶端要get的文件名
String fileName
=
request.getFileName();
File file
=
new
File(fileName);
//
如果文件存在,則將文件內容發送到socket的輸出流,即客戶端。
if
(file.exists())
{
sendFile(outStream, file);
}
else
{
System.out.println(
"
File
"
+
file.getCanonicalPath()
+
"
does not exist.
"
);
}
}
//
發送文件內容到客戶端,這里以HTTP 1.1的協議實現的
void
sendFile(BufferedOutputStream out, File file)
{
try
{
//
將文件內容全部讀入到一個字節數組中
DataInputStream in
=
new
DataInputStream(
new
FileInputStream(file));
int
len
=
(
int
) file.length();
byte
buffer[]
=
new
byte
[len];
//
完全讀取,然后關閉文件流
in.readFully(buffer);
in.close();
//
寫到socket的輸出流中
out.write(
"
HTTP/1.1 200 OK\r\n
"
.getBytes());
out.write((
"
Content-Length:
"
+
buffer.length
+
"
\r\n
"
).getBytes());
out.write(
"
Content-Type: text/HTML\r\n\r\n
"
.getBytes());
out.write(buffer);
out.flush();
out.close();
//
寫文件內容結束,log信息
System.out.println(
"
File sent:
"
+
file.getCanonicalPath());
System.out.println(
"
Number of bytes:
"
+
len);
}
catch
(Exception e)
{
try
{
//
發送失敗
out.write((
"
HTTP/1.1 400
"
+
"
No can do
"
+
"
\r\n
"
).getBytes());
out.write(
"
Content-Type: text/HTML\r\n\r\n
"
.getBytes());
}
catch
(IOException ioe)
{
}
System.out.println(
"
Error retrieving
"
+
file);
}
}
}
/** */
/**
* 實現讀客戶端請求的幫助類
*/
class
HTTPInputStream
extends
FilterInputStream
{
public
HTTPInputStream(InputStream in)
{
super
(in);
}
//
讀一行,當輸入流中沒有數據,或者讀到"\r\n"時,一行結束。
public
String readLine()
throws
IOException
{
StringBuffer result
=
new
StringBuffer();
boolean
finished
=
false
;
//
'\r'為回車符,值為13,'\n'為換行符,值為10
//
cr變量表示是否已經讀到換行符
boolean
cr
=
false
;
do
{
int
ch
=
-
1
;
//
讀一個字節
ch
=
read();
if
(ch
==
-
1
)
{
return
result.toString();
}
result.append((
char
) ch);
//
去掉最后的'\r\n'
if
(cr
&&
(ch
==
10
))
{
result.setLength(result.length()
-
2
);
return
result.toString();
}
//
讀到回車符,設置標識
if
(ch
==
13
)
{
cr
=
true
;
}
else
{
cr
=
false
;
}
}
while
(
!
finished);
return
result.toString();
}
//
得到所有的請求
public
HTTPRequest getRequest()
throws
IOException
{
HTTPRequest request
=
new
HTTPRequest();
String line;
do
{
//
依次讀取
line
=
readLine();
//
將請求填入容器
if
(line.length()
>
0
)
{
request.addLine(line);
}
else
{
break
;
}
}
while
(
true
);
//
返回
return
request;
}
}
//
客戶端請求的封裝類
class
HTTPRequest
{
//
請求的數據,按行存儲
Vector lines
=
new
Vector();
public
HTTPRequest()
{
}
public
void
addLine(String line)
{
lines.addElement(line);
}
//
判斷是否是Get請求
boolean
isGetRequest()
{
if
(lines.size()
>
0
)
{
//
獲取請求內容的第一行,如果頭三個字符是"GET",則為Get請求
String firstLine
=
(String) lines.elementAt(
0
);
if
(firstLine.length()
>
0
)
{
if
(firstLine.substring(
0
,
3
).equalsIgnoreCase(
"
GET
"
))
{
return
true
;
}
}
}
return
false
;
}
//
從請求中解析到文件名
//
一般第一行的消息如此類格式:"GET /hehe.htm HTTP/1.1"
/** */
/**
* 從請求中解析到文件名,只需要處理第一行即可。
* 第一行的格式有如下幾種:
* (1)如果請求的URL為"
http://localhost
:80/test/hehe.htm",
* 則第一行的內容為"GET /test/hehe.htm HTTP/1.1"。
* (2)如果請求的URL為"
http://localhost
:80",
* 則第一行的內容為"GET HTTP/1.1",此時應該找默認的html文件,如index.htm
* (3)如果請求的URL為"
http://localhost
:80/test",
* 則第一行的內容為"GET /test/ HTTP/1.1",此時應該找test目錄下默認的html文件
*/
String getFileName()
{
if
(lines.size()
>
0
)
{
//
得到vector中第一個元素
String firstLine
=
(String) lines.elementAt(
0
);
System.out.println(
"
firstLine:
"
+
firstLine);
//
根據http消息格式得到文件名
String fileName
=
firstLine.substring(firstLine.indexOf(
"
"
)
+
1
);
int
n
=
fileName.indexOf(
"
"
);
//
URL在兩個空格之間
if
(n
!=
-
1
)
{
fileName
=
fileName.substring(
0
, n);
}
//
去掉第一個'/'
try
{
if
(fileName.charAt(
0
)
==
'
/
'
)
{
fileName
=
fileName.substring(
1
);
}
}
catch
(StringIndexOutOfBoundsException ex)
{
}
//
默認首頁,這里認為index.htm為默認的首頁
//
類似于'
http://localhost
:80'的情況
if
(fileName.equals(
""
))
{
fileName
=
"
index.htm
"
;
}
//
類似于'
http://localhost
:80/download/'的情況
if
(fileName.charAt(fileName.length()
-
1
)
==
'
/
'
)
{
fileName
+=
"
index.htm
"
;
}
System.out.println(
"
fileName:
"
+
fileName);
return
fileName;
}
else
{
return
""
;
}
}
//
顯示請求信息
void
log()
{
System.out.println(
"
Received the following request:
"
);
for
(
int
i
=
0
; i
<
lines.size();
++
i)
{
System.out.println((String) lines.elementAt(i));
}
}
}
--
學海無涯
Powered by:
BlogJava
Copyright © 啥都寫點
主站蜘蛛池模板:
亚洲AV无码久久精品色欲
|
成人黄网站片免费视频
|
精品亚洲成a人片在线观看
|
男人的天堂亚洲一区二区三区
|
国产三级在线免费
|
水蜜桃视频在线观看免费
|
亚洲成人激情小说
|
精品亚洲国产成AV人片传媒
|
亚洲熟妇丰满多毛XXXX
|
免费无遮挡无码永久在线观看视频
|
免费99精品国产自在现线
|
伊人久久免费视频
|
a级毛片在线免费看
|
国产va免费精品
|
成人免费网站视频www
|
日本亚洲欧美色视频在线播放
|
亚洲深深色噜噜狠狠网站
|
亚洲嫩草影院在线观看
|
亚洲精品免费在线观看
|
亚洲AV午夜成人影院老师机影院
|
久久亚洲精品无码观看不卡
|
亚洲国产激情一区二区三区
|
俄罗斯极品美女毛片免费播放
|
国产色婷婷精品免费视频
|
在线免费观看中文字幕
|
成人免费午夜在线观看
|
免费可以在线看A∨网站
|
成人免费午夜视频
|
成年人视频在线观看免费
|
成年人免费网站在线观看
|
成人毛片18岁女人毛片免费看
|
久久精品免费一区二区喷潮
|
久久笫一福利免费导航
|
国国内清清草原免费视频99
|
全免费毛片在线播放
|
嫖丰满老熟妇AAAA片免费看
|
国产精品1024永久免费视频
|
无码日韩精品一区二区免费
|
最近中文字幕无吗免费高清
|
日韩高清免费观看
|
亚洲第一页日韩专区
|