博客地址首發(fā):http://www.icodeyou.com
之前做web應(yīng)用一直是在本地裝個(gè)Apache饵蒂、Tomcat之類的軟件慰于,然后把做好的網(wǎng)頁文件放在他們的工作目錄下(如Apache的htdocs),然后打開瀏覽器輸入127.0.0.1或localhost就可以直接訪問了,好神奇奄喂,可是為什么铐殃,怎么實(shí)現(xiàn)的呢,早就知道有Socket(套接字)這個(gè)東西跨新,可之前就是沒有把這兩方面結(jié)合起來富腊,今天我們就一起來看一看這究竟是為什么。
有同學(xué)說還不懂Socket是什么域帐,這東西很抽象赘被,在計(jì)算機(jī)網(wǎng)絡(luò)原理里講協(xié)議時(shí)才會看到,今天咱們完全忽略太嚴(yán)謹(jǐn)肖揣、學(xué)術(shù)的定義民假,就來看看Socket到底是什么。想象一下许饿,你把電腦的電源插在插座上阳欲,你的電腦就可以使用了,為什么陋率?“這不是廢話嗎球化!”確實(shí),咱們來想一下這個(gè)過程瓦糟,你拿著插頭插在了插座上筒愚,然后你的電腦和千里之外的供電廠就能“通信”了,把你的電腦想成是客戶端菩浙,把千里之外的供電廠想成是服務(wù)器巢掺,通過插座和很長很長的線纜你們就可以勾搭上了,那么Socket在這其中相當(dāng)于什么呢劲蜻?“插座陆淀!”沒錯,就是插座先嬉!對于我的電腦來說轧苫,我想讓它通電工作,我只需要個(gè)插座就行了啊疫蔓,什么插座是什么材質(zhì)的含懊,線纜是什么型號的,供電廠到底在什么經(jīng)緯度衅胀,電力到底怎么傳輸岔乔,我管它干嘛呢,都跟我沒關(guān)系滚躯!我只要知道我需要的不是整個(gè)世界雏门,而是嘿歌。。剿配。一個(gè)插座搅幅!讀到這里阅束,想必同學(xué)已經(jīng)對“插座”有了很森的理解了呼胚;再舉一個(gè)例子,你和基友的電腦通過有線的方式連上了同一個(gè)路由器息裸,這個(gè)時(shí)候你們就可以直接通過內(nèi)網(wǎng)IP地址進(jìn)行訪問了蝇更,在這個(gè)過程中,那個(gè)方方的接口(RJ45接口)就是“Socket”呼盆,反正插上“Socket”就能用年扩,我不用管到底通過Socket怎么能夠?qū)崿F(xiàn)通信。在計(jì)算機(jī)編程的網(wǎng)絡(luò)世界里访圃,作為應(yīng)用程序厨幻,我只需要一個(gè)“插座”就可以和任何服務(wù)器通信了,想想都有點(diǎn)小激動呢~~~
接下來要講的就是腿时,電腦電源需要一個(gè)socket去插上况脆,那么發(fā)電廠呢,也同樣需要一個(gè)插座插上去來給你供電——也就是說批糟,發(fā)電廠需要一個(gè)“插座”格了!。徽鼎。盛末。廢話,否淤,悄但,,沒錯石抡,確實(shí)是這樣檐嚣,服務(wù)器端也需要一個(gè)“插座”,只不過它叫做ServerSocket(這看起來像是繼承自Socket汁雷,我也不知道净嘀,待查)。
有了“插座”(Socket)的概念之后侠讯,我們就可以愉快地讓電腦(客戶端)與發(fā)電廠(服務(wù)器)通信了挖藏。無論是客戶端還是服務(wù)器,都需要Socket厢漩,鑒于咱們今天的題目是“搭建web服務(wù)器”膜眠,所以咱們接下來就來看一下怎么創(chuàng)建服務(wù)器的ServerSocket。說道這里,有同學(xué)就會問到了宵膨,“難道客戶端不需要Socket嗎架谎?”,確實(shí)需要辟躏,因?yàn)槲覀兪怯脼g覽器訪問本機(jī)IP“127.0.0.1”谷扣,所以客戶端的Socket就由瀏覽器自己維護(hù)了,不需要咱們動手寫的捎琐』嵯眩“可是我還是不明白為什么在瀏覽器里輸入127.0.0.1之后就可以看到我的網(wǎng)頁了?求解釋” 好瑞凑,那咱們慢慢來末秃,先動手編寫一個(gè)服務(wù)器端的ServerSocket吧啦啦啦~
創(chuàng)建服務(wù)器端Socket的步驟如下:
1、創(chuàng)建ServerSocket對象
ServerSocket serverSocket = new ServerSocket(“80”);
//這里只需要指明當(dāng)前程序監(jiān)聽80號端口就可以了籽御,至于為什么是80练慕,因?yàn)槲蚁矚g!“好霸道技掏。铃将。×憬兀”因?yàn)槲覀円O(jiān)聽web請求麸塞,默認(rèn)就是80號端口。其實(shí)涧衙,1-1024端口被操作系統(tǒng)占用了哪工,1025-65535的端口你隨便用,只要不會和其他應(yīng)用程序沖突就可以(別用什么類似3389這么常用的端口就好了弧哎。雁比。。)
2撤嫩、作為服務(wù)器偎捎,我要知道,我的使命就是要等待客戶端發(fā)來請求序攘,也就是客戶端發(fā)來Socket茴她,我首先要把它Hold住程奠!
Socket socket = serverSocket.accept();
//這里需要特別說明一下丈牢,accept方法比較特殊,它是一個(gè)阻塞方法(block method)瞄沙,因?yàn)橹灰炔粊砜蛻舳税l(fā)來的請求(Socket)己沛,它就一直等下去而不會繼續(xù)執(zhí)行它下面的代碼慌核。唉,此等癡情人怎么跟我一樣O(∩_∩)O
3申尼、客戶端要向我表白垮卓,給我發(fā)來情書,那我作為服務(wù)器只要得到它的輸入就好了
InputStream inputStream = socket.getInputStream();
//注意师幕,客戶端發(fā)來的表白信息都在socket里面粟按,而不是serverSocket里面,這點(diǎn)要是弄錯了们衙,讀不到情書內(nèi)容钾怔,活該你單身。(我只有冷笑蒙挑。。愚臀。)
4忆蚀、收到了情書,我好想知道里面究竟寫了什么肮昧选馋袜!迫!不舶斧!及欣鳖!待! 好茴厉,開始解析情書內(nèi)容
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
//java包裝類泽台,只為讀到寫給我的情書,耶~
String line = “”;
while ( (line = reader.readLine()) != null ){
System.out.println(line);
}
5矾缓、組裝前4步的代碼怀酷,會要求try catch一下異常,正常捕獲就好 下面貼代碼
public class MultiWebServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(80);
System.out.println("正在等待情書中...");
Socket socket = serverSocket.accept();
System.out.println("收到情書嗜闻,我要開始解析蜕依!");
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while ( (line = reader.readLine()) != null ){
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
好了,服務(wù)器端的代碼咱們寫完了琉雳,那接下來干啥样眠?不知道。翠肘。檐束。不過還記得剛才提出的問題嗎——“可是我還是不明白為什么在瀏覽器里輸入127.0.0.1之后就可以看到我的網(wǎng)頁了?”那就試試唄锯茄,看看咱們?nèi)绻跒g覽器里輸入127.0.0.1或者localhost會怎么樣
首先必須把剛才咱們編寫的服務(wù)器端程序運(yùn)行起來厢塘,然后再打開瀏覽器茶没,記住,必須先運(yùn)行服務(wù)器端程序晚碾,不然情書就發(fā)丟了抓半。。格嘁。運(yùn)行服務(wù)器端程序笛求,如圖:
注意紅圈中的兩點(diǎn):由于此時(shí)沒有客戶端發(fā)來情書,還記得剛才的accept()阻塞方法嗎糕簿,它就一直等啊等探入,等不來我還等,所以紅圈中會顯示“正在等待情書中…”懂诗;那么右面那個(gè)箭頭指向的是什么意思呢蜂嗽,一個(gè)紅色停止的圖標(biāo),也就是說殃恒,這個(gè)程序現(xiàn)在一直在執(zhí)行著植旧,沒有結(jié)束,就好像死循環(huán)一樣(當(dāng)然這里絕對不是死循環(huán)离唐,其實(shí)是阻塞病附,只是死的樣子好像死循環(huán),一會咱們會談到死循環(huán)的亥鬓,別著急完沪,遲早會死的)
接下來打開瀏覽器,在地址欄輸入127.0.0.1/index.html后回車嵌戈,看看瀏覽器什么反應(yīng)覆积。。咕别。技健。。一段時(shí)間過去了惰拱,瀏覽器居然一點(diǎn)反應(yīng)都沒有雌贱,然后告訴我該頁無法顯示。我去偿短。欣孤。。難道講了這么多咱們就這么失敗了嗎昔逗,我哭降传。那就打開eclipse看一眼吧,看看服務(wù)器端有沒有什么動靜啊勾怒。打開服務(wù)器端一看婆排,臥槽声旺,瞬間世界向我問好了!
注意看紅筆標(biāo)注段只,我收到了情書腮猖!我要開始解析了!那到底情書里是什么內(nèi)容赞枕,別問我澈缺,繼續(xù)向下看】簧簦“好熟悉的一段報(bào)文姐赡,我們好像在哪見過,還記得嗎柠掂,那是一個(gè)春天项滑,你剛發(fā)芽兒。陪踩。杖们。”沒錯肩狂,這就是計(jì)算機(jī)網(wǎng)絡(luò)原理講的http請求報(bào)文。沒有學(xué)過計(jì)網(wǎng)怎么辦姥饰,沒關(guān)系傻谁,看前兩行(其實(shí)我們一會用到的也只有第一行而已),“我看到了index.html” 是的列粪,這是剛才我們在瀏覽器里面輸入的地址审磁;第二行,“我也看到了127.0.0.1”岂座,是的态蒂,也是我們剛剛在瀏覽器里面輸入的。這說明了什么费什?激動的我無法說出這到底說明了什么钾恢,但想必讀者你已經(jīng)揣測出了什么。
寫到這里鸳址,作為服務(wù)器的我已經(jīng)收到了從客戶端發(fā)來的情書瘩蚪,那客戶端(瀏覽器)為什么一點(diǎn)反應(yīng)都沒有呢,甚至過了一會就“該頁無法顯示”了稿黍。因?yàn)榘≌钍荩思医o你寫了情書,你沒回復(fù)人家巡球,人家等了一會覺得沒戲了就傷心欲絕了言沐!是啊邓嘹,喜不喜歡人家都要和他說一聲的,給他個(gè)答復(fù)险胰,哪怕只說:“對不起汹押,你是個(gè)好人。鸯乃。鲸阻。”
走神了吧缨睡?好像說到自己了吧鸟悴?回來吧,咱們現(xiàn)在的任務(wù)呢奖年,就是怎么給人家個(gè)答復(fù)细诸。
怎么給,怎么給陋守,怎么給震贵。。水评⌒上担快想快想,既然人家都指明了想和127.0.0.1里的“index.html”表白中燥,那當(dāng)然就得由index.html來給他答復(fù)嘍寇甸。怎么答,怎么答疗涉,怎么答拿霉。。咱扣≌捞裕快想快想,既然index.html是個(gè)文件闹伪,那我讀出文件內(nèi)容后直接發(fā)給客戶端不就行了嗎沪铭?可是用什么發(fā)?沒錯祭往,是socket伦意!我們用socket把文件的內(nèi)容返回給客戶端就好了。
那么問題來了硼补。驮肉。∫押В“說的非常好离钝,關(guān)鍵是怎么做票编!”——首先怎么讀出文件來?
假定咱們的index.html在我電腦的E://課件/計(jì)算機(jī)網(wǎng)絡(luò)原理/實(shí)驗(yàn)/實(shí)驗(yàn)1/ 文件夾下卵渴,并且假定不會跨域訪問慧域,則:
1、定義一個(gè)字符串浪读,用來存咱們的工作目錄
String base_url = "E://課件/計(jì)算機(jī)網(wǎng)絡(luò)原理/實(shí)驗(yàn)/實(shí)驗(yàn)1/";
//這只是我本機(jī)的目錄昔榴,至于到了你的電腦上,你可以自己更改</span>
2碘橘、我怎么通過報(bào)文知道客戶端要和index.html表白互订?看情書第一行 GET /index.html HTTP/1.1,所以只需要獲取情書的第一行字符串并解析出index.html就好辦啦痘拆,easy仰禽,開始吧
//由于目前只需要第一行,所以咱們就不像上面那樣循環(huán)讀取了纺蛆,讀一行就夠了
String line = reader.readLine();
//用字符串截取函數(shù)吐葵,把“index.html”這個(gè)字符串給揪出來
String url = line.substring(5, line.indexOf("HTTP") - 1);
3、所以咱們index.html的絕對路徑就是 base_url + url 了桥氏,終于把我愛的人從人山人海中找到了温峭,看看她怎么答復(fù)我吧——獲取文件內(nèi)容
inputStream = new FileInputStream(base_url + url);
OutputStream outputStream = socket.getOutputStream(); //我要從服務(wù)器給客戶端答復(fù)了,對于服務(wù)器來說字支,這是發(fā)出去的內(nèi)容诚镰,所以是Out!
byte[] buffer = new byte[4 * 1024]; //定義字節(jié)緩沖區(qū)
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len); //很重要祥款!通過socket的outputStream把咱們解析出來的文件內(nèi)容一字不落的發(fā)出去 如果沒寫這個(gè),導(dǎo)致你愛的跟你表白的抑郁而死月杉,活該你單身
}
outputStream.flush(); //如果最后一次write時(shí)沒有把buffer寫滿刃跛,是不會自動發(fā)出去的,需要調(diào)用flush方法強(qiáng)制把內(nèi)容從緩沖區(qū)發(fā)出去
好了苛萎,文件讀取出來了桨昙,也返回給客戶端了,親愛噠他能收到嗎腌歉?還是一樣蛙酪,務(wù)必先運(yùn)行服務(wù)器端程序,然后打開瀏覽器輸入127.0.0.1/index.html 后回車示罗。我緊張击吱,我激動刊愚,能不能收到回復(fù)性宏,會給我什么樣的回復(fù)阁危?如圖玛痊。。狂打。
為什么會這樣擂煞??趴乡?6允 !晾捏! 好吧蒿涎,看看女神的index.html文件里都寫了些什么。粟瞬。同仆。
<html>
<head>
<meta charset="utf-8" />
<title>Welcome</title>
</head>
<body>
<h1>王歡,你是個(gè)好人... </h1>
</body>
</html>
看到這里裙品,我到底應(yīng)該高興還是欲絕俗批。。市怎。高興的是岁忘,我女神給我答復(fù)了;欲絕的是区匠。干像。。那么問題來了驰弄,麻汰,,學(xué)表白技術(shù)哪家強(qiáng)戚篙?
玩笑歸玩笑五鲫,那我們的針對這次的淺談題目是不是就完成了?可以說是的岔擂,但是我表白一次失敗就算了位喂?我還要表白第二次!(其實(shí)我倒不是這樣的乱灵,這里只能犧牲我的人品來為了大家更好的理解了塑崖,呵呵)。好吧痛倚,我剛才的工作目錄下還有個(gè)another.html规婆,這次我來跟她表白吧!好!繼續(xù)在瀏覽器中輸入127.0.0.1/another.html后回車聋呢,期待這次會表白成功苗踪。可是我等啊等削锰,瀏覽器在那里打圈圈通铲,難道瀏覽器都知道我太花心了,拒絕幫我傳遞情書器贩?好吧颅夺,我再打開瀏覽器試一下,輸入127.0.0.1/index.html 蛹稍,嗯吧黄?連第一個(gè)女神都不理我了?唆姐!我靠拗慨!為毛!
沖動是魔鬼奉芦!冷靜赵抢!我打開eclipse控制臺,發(fā)現(xiàn)服務(wù)器根本就沒有“正在等待情書中…”声功,所以我拜托瀏覽器發(fā)過去的情書當(dāng)然就發(fā)丟了烦却,因?yàn)楦緵]人在接收啊。(竊喜先巴,還好不是因?yàn)槲姨ㄐ牧怂詾g覽器沒有幫我投遞情書)可是為什么呢其爵?
冷靜吧,分析代碼伸蚯。其實(shí)我們可以想到摩渺,這段代碼執(zhí)行完一次后不就結(jié)束了嗎,那我第二次給她發(fā)請求她當(dāng)然會收不到了剂邮。對啊证逻,那為了解決這個(gè)問題,怎么辦呢抗斤?跪求紅娘支招!
紅娘說:“給服務(wù)器程序個(gè)死循環(huán)吧丈咐,讓她反復(fù)在等客戶端的請求就好了瑞眼。”(其實(shí)紅娘就一直在死循環(huán)中)
紅娘果然是紅娘(不然是誰棵逊。伤疙。。),那就按照她的說法試一試唄徒像!改代碼黍特,加入 while (true) 死循環(huán):
public class MultiWebServer {
public static void main(String[] args) {
String base_url = "E://課件/計(jì)算機(jī)網(wǎng)絡(luò)原理/實(shí)驗(yàn)/實(shí)驗(yàn)1/";
while (true) {
try {
ServerSocket serverSocket = new ServerSocket(80);
System.out.println("正在等待情書中...");
Socket socket = serverSocket.accept();
System.out.println("收到情書,我要開始解析锯蛀!");
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream));
String line = reader.readLine();
System.out.println(line);
String url = line.substring(5, line.indexOf("HTTP") - 1);
System.out.println("情書解析完畢灭衷,我要想想怎么回復(fù)了...");
// 獲取文件內(nèi)容
inputStream = new FileInputStream(base_url + url);
OutputStream outputStream = socket.getOutputStream();
byte[] buffer = new byte[4 * 1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
outputStream.flush();
System.out.println("情書請求已發(fā)送給客戶端");
//關(guān)閉對應(yīng)的資源
serverSocket.close();
socket.shutdownInput();
socket.close();
inputStream.close();
reader.close();
outputStream.close();
} catch (Exception e) {
}
}
}
}
這樣,這位紅娘就在這里一直等啊等旁涤,來了一個(gè)客戶端我就處理他的情書請求翔曲,處理完這個(gè)繼續(xù)循環(huán)以相同的方式等,處理劈愚,等瞳遍,處理。菌羽。掠械。。
好吧注祖,咱們接下來試一下猾蒂,還是務(wù)必先運(yùn)行服務(wù)器端程序,然后先和第一個(gè)女神表白氓轰,即 127.0.0.1/index.html 還是好朋友的話婚夫,就別問我返回結(jié)果。署鸡。案糙。這個(gè)時(shí)候打開eclipse的控制臺,有沒有發(fā)現(xiàn)右上角的紅色暫停標(biāo)志可以點(diǎn)擊靴庆,那就說明咱們的紅娘還在兢兢業(yè)業(yè)的工作著时捌!好了,抓緊時(shí)間趕緊向第二個(gè)女神表白炉抒,看她怎么說奢讨, 瀏覽器輸入 127.0.0.1/another.html ,回車焰薄!好快啊拿诸,女神給我答復(fù)了。塞茅。亩码。
這。野瘦。描沟。(她怎么知道不到十分鐘飒泻?你是不是突然想到了cookie可以記錄客戶端的信息,不過咱們這里沒用到cookie)還是看看another.html文件里寫了什么吧
<html>
<head>
<meta charset="utf-8" />
<title>Welcome</title>
</head>
<body>
<h1>我記得你剛和別人表白吧吏廉,還不過十分鐘泞遗,你怎么會是個(gè)好人!</h1>
</body>
</html>
好吧席覆,我啥也不說了史辙,親們,我還要向第三個(gè)女神表白嗎娜睛。髓霞。。畦戒?瀏覽器主動跟我說:“你表白吧方库,這次你發(fā)多少封表白信我都能給你送到服務(wù)器那里,因?yàn)樗恢痹诘却医o她發(fā)送呢障斋!”想想纵潦,還是算了,人生如此垃环,何須多言邀层。。遂庄。
代碼都貼出來了寥院,其實(shí)看起來挺簡單的,但是實(shí)際操作中會碰到各種各樣的問題涛目。
還有一些要再繼續(xù)嘮叨的邊角料:
- 1秸谢、Q:什么是端口?
A:這是一個(gè)比較抽象的概念霹肝,是為了進(jìn)程間通信估蹄,每一個(gè)進(jìn)程只能占用一個(gè)端口,也就是說多個(gè)進(jìn)程絕不能同時(shí)占用一個(gè)端口
- 2沫换、Q:既然多個(gè)進(jìn)程不能同時(shí)占用一個(gè)端口臭蚁,那么咱們常說的web服務(wù)默認(rèn)使用的是80端口,我電腦有三個(gè)瀏覽器讯赏,谷歌垮兑,360,IE他們卻可以同時(shí)上網(wǎng)漱挎,這不是端口沖突了嗎甥角?
A:常說的web服務(wù)使用80端口指的是服務(wù)器監(jiān)聽web請求的端口,是服務(wù)器识樱,不是你自己的客戶機(jī)。一般來說,一個(gè)應(yīng)用程序打開后訪問網(wǎng)絡(luò)本地操作系統(tǒng)為其分配的端口號是隨機(jī)的怜庸,所以三個(gè)瀏覽器雖然同時(shí)接收web服務(wù)器的回復(fù)報(bào)文当犯,由于他們?nèi)齻€(gè)各自占用的端口不一樣,所以不會產(chǎn)生沖突割疾。
- 3嚎卫、Q:既然我的應(yīng)用程序使用的端口都是隨機(jī)的,服務(wù)器接收到請求后怎么知道它要把應(yīng)答報(bào)文發(fā)給誰宏榕?
A:靠Socket拓诸!通過剛才的編程實(shí)戰(zhàn),在我理解麻昼,Socket肯定會至少包括四部分內(nèi)容:IP地址奠支,端口號,輸入流和輸出流抚芦。也就是說倍谜,從客戶機(jī)發(fā)給服務(wù)器的Socket里一定會有客戶機(jī)的IP地址和相應(yīng)應(yīng)用程序的端口號,這樣服務(wù)器自然就知道應(yīng)該把應(yīng)答報(bào)文發(fā)給誰了叉抡。
- 4尔崔、Q:非要使用80端口嗎?
A:不一定褥民。我們剛才在編程的時(shí)候確實(shí)使用的是80端口季春,所以我們在瀏覽器中輸入127.0.0.1/index.html,瀏覽器會默認(rèn)認(rèn)為我們會向127.0.0.1主機(jī)的80號端口發(fā)送請求消返。但是载弄,這個(gè)80端口號只是默認(rèn)的而已,我們完全可以自己改掉侦副,比如在java代碼里把服務(wù)器端的ServerSocket改成 ServerSocket serverSocket = new ServerSocket(3456); 這時(shí)候我們在瀏覽器中就要輸入 127.0.0.1:3456/index.html 了侦锯,效果是一樣的,可以淺嘗輒止一下秦驯。
- 5尺碰、Q:誰是客戶端,誰是服務(wù)器译隘?
A:咱們只有一臺電腦亲桥,這臺電腦既充當(dāng)著客戶端的角色,又充當(dāng)著服務(wù)器的角色固耘。當(dāng)瀏覽器請求網(wǎng)頁時(shí)题篷,它是客戶端;當(dāng)80端口收到請求報(bào)文并應(yīng)答時(shí)厅目,它就是服務(wù)器番枚。實(shí)在不理解法严,就想想什么是自戀吧,或者葫笼,自交也勉強(qiáng)可以深啤。。
- 6路星、Q:還有什么問題溯街,歡迎留言~
對于此用java編寫的web服務(wù)器的一點(diǎn)簡單說明:此段代碼非常簡單,所以肯定不會是真正web服務(wù)器所用到的代碼洋丐,咱們這個(gè)只是能夠應(yīng)答最最基本的web請求呈昔,不能檢測是否跨域訪問等等。不過最基本的友绝,用的socket編程是肯定的堤尾。另外,對于此段程序九榔,只給出了處理輸入輸出流的一種方式哀峻。對于輸入流,除了咱們剛才用到的BufferedReader包裝類哲泊,還可以直接用InputStream的read()方法等剩蟀;對于輸出流,除了咱們剛才用的OutputStream的write()方法切威,還可用BufferedWritter育特,PrintWritter等,這些都是java IO的基本用法先朦,根據(jù)網(wǎng)絡(luò)環(huán)境缰冤,根據(jù)所要讀取的文件大小來時(shí)時(shí)變通,這就是仁者見仁智者見智了喳魏。
文章寫到了最后棉浸,不知道該怎么收尾了,安安靜靜做個(gè)程序員吧刺彩,挺好迷郑。
個(gè)人github: http://github.com/icodeu
代碼托管地址:https://github.com/icodeu/JavaForWebServer
CSDN博客:http://blog.csdn.net/icodeyou
個(gè)人微信號:qqwanghuan
只為技術(shù)交流
