1.Client Program ServerProgram
|_________ 計(jì)算機(jī)網(wǎng)絡(luò)____________|
1.如張三給李四寄信,其不必親自送到李四家里.送信任務(wù)由郵政網(wǎng)絡(luò)完成.其只需提供李四的地址,郵政網(wǎng)絡(luò)即可準(zhǔn)確將的將信送達(dá)目標(biāo)地址.
2.server與client program只關(guān)心什么樣的數(shù)據(jù)發(fā)送給對方,而不必考慮數(shù)據(jù)如何傳輸給對方.傳輸任務(wù)由計(jì)算機(jī)網(wǎng)絡(luò)完成.
3.網(wǎng)絡(luò)應(yīng)用程序建立在計(jì)算機(jī)網(wǎng)絡(luò)的基礎(chǔ)上.
2.進(jìn)程之間的通信:
1.java EchoPlayer,啟動EchoPlayer進(jìn)程,該進(jìn)程執(zhí)行main(啟動了一個JVM進(jìn)程)
2.client-> 本地控制臺->System.in,標(biāo)準(zhǔn)輸入->EchoPlayer進(jìn)程
System.out,標(biāo)準(zhǔn)輸出<-
3.響應(yīng)結(jié)果移到遠(yuǎn)程主機(jī)->EchoClient & EchoServer
client->客戶機(jī)控制臺->EchoClient進(jìn)程 --------->網(wǎng)絡(luò)--------->遠(yuǎn)程主機(jī)服務(wù)器,EchoServer進(jìn)程
<--------網(wǎng)絡(luò)<--------
1.如張三,李四通話,前提是他們的電話機(jī)投連接到電話網(wǎng)絡(luò).二者只關(guān)心談話內(nèi)容,而不必考慮語言如何傳輸?shù)綄Ψ诫娫捝?傳輸語音任務(wù)由電話網(wǎng)絡(luò)完成.
2.兩個進(jìn)程順利通信的前提是所在主機(jī)都連接到計(jì)算機(jī)網(wǎng)網(wǎng)絡(luò)上.EchoClient和EchoServer只關(guān)注通信具體內(nèi)容,無需考慮如何傳送給對方.傳輸信息的任務(wù)由計(jì)算機(jī)網(wǎng)絡(luò)來完成.
3.計(jì)算機(jī)網(wǎng)絡(luò)的概念
1.通俗的講計(jì)算機(jī)網(wǎng)絡(luò)即通過電纜,電話線或無線通信設(shè)施等互聯(lián)的計(jì)算機(jī)集合.網(wǎng)絡(luò)中每臺機(jī)器成為節(jié)點(diǎn).
2.本書節(jié)點(diǎn)一詞指網(wǎng)絡(luò)中任意一個設(shè)備,用主機(jī)指網(wǎng)絡(luò)中的計(jì)算機(jī)節(jié)點(diǎn).
3.人與人之前通過某種語言來交流,網(wǎng)絡(luò)中的主機(jī)也通過"語言交流",這樣語言稱為網(wǎng)絡(luò)協(xié)議.-->通俗解釋.
4.網(wǎng)絡(luò)中每個主機(jī)都有地址,其是用于標(biāo)識主機(jī)的一個字節(jié)序列.字節(jié)序列越長,標(biāo)識的地址數(shù)目就越多,更多的設(shè)備可連入網(wǎng)絡(luò).
5.上海人講上海話,廣東人將廣東話,上海人與廣東人用普通話溝通。與此類似,不同網(wǎng)絡(luò)之間的互聯(lián)網(wǎng)靠網(wǎng)絡(luò)上的標(biāo)準(zhǔn)語言-TCP/IP協(xié)議.
4.OSI參考模型
1.計(jì)算機(jī)網(wǎng)絡(luò)之初,每個計(jì)算機(jī)廠商都有一套自己的網(wǎng)絡(luò)體系結(jié)構(gòu),互不相容.->ISO->OSI(Open System Interconnection)體系結(jié)構(gòu)->Open一詞以為一個網(wǎng)絡(luò)系統(tǒng)只要遵循該模型,即可與世界上任何地方的也遵循osi模型的其他網(wǎng)絡(luò)系統(tǒng)連接.
2.osi把網(wǎng)絡(luò)分為7層,物理層,數(shù)據(jù)鏈路層,網(wǎng)絡(luò)層,傳輸層,會話層,表示層和應(yīng)用層.每一層使用下層提供的服務(wù)并為上層提供服務(wù).
3.不同主機(jī)之間的相同層稱為對等層.
4.osi各層主要功能:
1.物理層:物理介質(zhì)->第0層.->為上一層提供物理連接,規(guī)定通信節(jié)點(diǎn)之間的機(jī)械和電器等特性,如規(guī)定電纜和接頭的類型,傳送信號的電壓等->bit流傳輸->hub(集線器).
2.數(shù)據(jù)鏈路層:兩個相鄰節(jié)點(diǎn)的線路->無差錯以幀傳輸.->建立,維持和釋放數(shù)據(jù)鏈路的連接->接收方檢測所傳數(shù)據(jù)有差錯->通知發(fā)送方重發(fā)這一幀->switch(交換機(jī))
3.網(wǎng)絡(luò)層:兩個計(jì)算機(jī)之間->經(jīng)過多個數(shù)據(jù)鏈路->多個通信子網(wǎng)->選擇合適的網(wǎng)間路由和交換節(jié)點(diǎn)->確保數(shù)據(jù)及時傳到目標(biāo)主機(jī).>將數(shù)據(jù)鏈路層提供的幀組成數(shù)據(jù)包->網(wǎng)絡(luò)包頭包含有邏輯地址-源主機(jī)和目標(biāo)主機(jī)的網(wǎng)絡(luò)地址->Router(路由器).
->兩個相鄰節(jié)點(diǎn)之間的線路成為數(shù)據(jù)鏈路.數(shù)據(jù)鏈路層負(fù)責(zé)數(shù)據(jù)鏈路上的數(shù)據(jù)傳輸->主機(jī)A到主機(jī)B的整個路徑成為路由.->網(wǎng)絡(luò)層負(fù)責(zé)合適的路由.
4.傳輸層:為源主機(jī)和目標(biāo)主機(jī)的會話層提供建立,維護(hù)和取消傳輸連接的功能->以可靠方式或者不可靠方式(數(shù)據(jù)有可能丟失或者出錯)傳輸數(shù)據(jù).>報文
5.會話層:管理進(jìn)程之間的會話過程.即負(fù)責(zé)簡歷,管理,終止進(jìn)程之間的繪畫.->在數(shù)據(jù)中插入校驗(yàn)點(diǎn)來實(shí)現(xiàn)數(shù)據(jù)的同步.
6.表示層:數(shù)據(jù)轉(zhuǎn)換,保證一個主機(jī)的應(yīng)用層數(shù)據(jù)可以被另一個主機(jī)的應(yīng)用層理解.->加密,解密,壓縮,解壓和格式轉(zhuǎn)換等.
7.應(yīng)用層:確定進(jìn)程之間通信的實(shí)際用途.
1.源主機(jī)->發(fā)送數(shù)據(jù)->目標(biāo)主機(jī)->由上層向下層傳遞->每一層給上一層傳遞的數(shù)據(jù)加上一個header->向下層發(fā)出->通過物理介質(zhì)傳輸?shù)侥繕?biāo)主機(jī)->下層向上層傳遞->每一層先對數(shù)據(jù)進(jìn)行處理,去掉header.->達(dá)到最上層->還原成實(shí)際數(shù)據(jù).
2.各個層加入的header有著不同的內(nèi)容.如果網(wǎng)絡(luò)層加入的header包括源地址和目標(biāo)地址等.->傳輸層header包括報文類型,源端口和目標(biāo)端口等,序列號和應(yīng)答號等.
3.數(shù)據(jù)鏈路層還會為數(shù)據(jù)加上信息尾.
4.發(fā)送方->數(shù)據(jù)由上至下->封裝->傳給下層->接收方->數(shù)據(jù)由下至上->解封裝->傳給上層;生活中也常采用該方式.如寄信.->信->信封->寫上發(fā)信人和收信人地址.->接收方->拆開信封.
5.osi參考模型將網(wǎng)絡(luò)層分為多個層次,每個層次分工明確.->簡化網(wǎng)路系統(tǒng)設(shè)計(jì)過程.->如設(shè)計(jì)設(shè)計(jì)傳輸層,只需考慮如何在兩個主機(jī)傳送數(shù)據(jù);設(shè)計(jì)網(wǎng)絡(luò)層,只需考慮如何在網(wǎng)絡(luò)上找到一條發(fā)送數(shù)據(jù)的路徑了即路由.
6.對等層之間互相通信需要遵守規(guī)則,如通信的格式和通信內(nèi)容.->網(wǎng)絡(luò)協(xié)議.
7.osi沒有具體實(shí)現(xiàn)方式,只不過為其他組織制定網(wǎng)絡(luò)協(xié)議提供了參考框架.
5.TCP/IP參考模型
1.OSI參考模型過于龐大和復(fù)雜,難以投入到實(shí)際運(yùn)用.->TCP/IP參考模型->簡化->在網(wǎng)絡(luò)各層(除了主機(jī)-網(wǎng)絡(luò)層)外都提供了完善的協(xié)議->TCP/IP協(xié)議集->工業(yè)標(biāo)準(zhǔn)/事實(shí)標(biāo)準(zhǔn).
2.4個層次:應(yīng)用層->傳輸層->網(wǎng)絡(luò)互聯(lián)層->主機(jī)-網(wǎng)絡(luò)層.IP協(xié)議和TCP協(xié)議時協(xié)議集中最核心的兩個協(xié)議.
3.
1.主機(jī)網(wǎng)絡(luò)層:TCP/IP參考模型沒有提供者這一層的實(shí)現(xiàn),也沒有提供協(xié)議.->第三方實(shí)現(xiàn)的該層能為上層網(wǎng)絡(luò)互聯(lián)層提供訪問接口->傳遞IP數(shù)據(jù)包->IEEE802.3(以太網(wǎng))->IEEE802.4(令牌環(huán)網(wǎng))
2.網(wǎng)絡(luò)互聯(lián)層:把IP數(shù)據(jù)包發(fā)送到目標(biāo)主機(jī)->將原始數(shù)據(jù)分發(fā)成多個數(shù)據(jù)包,沿不同的路徑同時傳遞數(shù)據(jù)包(為了盡快的發(fā)送數(shù)據(jù))->數(shù)據(jù)包達(dá)到的順序和發(fā)送的先后順序可能不同->需要上層傳輸層對數(shù)據(jù)包重新排序,還原為原始數(shù)據(jù).
該層具有連接異構(gòu)網(wǎng)的功能.如以太網(wǎng)和令牌環(huán)網(wǎng),二者都向網(wǎng)絡(luò)互聯(lián)層提供了統(tǒng)一非訪問接口,訪問接口向上層隱藏了下層網(wǎng)絡(luò)的差異,使得兩個網(wǎng)絡(luò)之間可以順利傳遞數(shù)據(jù)包。
采用IP協(xié)議,其規(guī)定了數(shù)據(jù)包的格式,并規(guī)定了為數(shù)據(jù)包尋找路由的流程.
3.傳輸層:使源主機(jī)和目標(biāo)主機(jī)上的進(jìn)程可以進(jìn)行會話.
1.TCP:傳輸控制協(xié)議.面向連接,可靠.將源主機(jī)的字節(jié)流無差錯的發(fā)送給互聯(lián)網(wǎng)的目標(biāo)主機(jī).發(fā)送端將上層傳下來的數(shù)據(jù)分成報文段傳遞給下層->接收端將受到的報文進(jìn)行重組后遞給上層->處理端到端的流量控制,避免接收速度慢的接收方?jīng)]有足夠的緩沖區(qū)來接收發(fā)送方發(fā)送的大量數(shù)據(jù).
2.UDP:用戶數(shù)據(jù)包協(xié)議.->不可靠,無連接.適用于不需要對報文進(jìn)行排序和流量控制的場合.不能保證數(shù)據(jù)包的接收順序和發(fā)送順序一致,甚至不能保證是否全部達(dá)到目標(biāo)主機(jī).
4.應(yīng)用層:
將osi參考模型的會話層和表示層功能合并到應(yīng)用層.
基于TCP:
1.FTP:文本傳輸協(xié)議,網(wǎng)絡(luò)上傳輸文件
2.TELNET:虛擬終端協(xié)議.允許從主機(jī)A登陸到遠(yuǎn)程主機(jī)B,使得主機(jī)允許充當(dāng)遠(yuǎn)程主機(jī)B的虛擬終端
3.HTTP:超文本傳輸協(xié)議,允許傳送超文本
4.HTTPS:安全超文本傳輸協(xié)議.數(shù)據(jù)加密->解密
POP3,IMAP4,SMTP...
基于UDP:
SNMP,DNS
6.IP協(xié)議
1.IP網(wǎng)絡(luò),即在網(wǎng)絡(luò)層采用IP協(xié)議的網(wǎng)絡(luò)中每臺主機(jī)都一個唯一的ip地址,用來標(biāo)識網(wǎng)絡(luò)中的每個主機(jī).->32位的二進(jìn)制數(shù)序列.->32位分為4個單元,每個單元占8位,十進(jìn)制數(shù)標(biāo)識每個單元(這樣就很方便表示了).->10進(jìn)制數(shù)的取值范圍是0-255.
如192.168.3.4
->新的IPV6標(biāo)準(zhǔn)將采用128位的地址,大大擴(kuò)充了可用地址的數(shù)目.
2.IP地址由兩部分組成:IP網(wǎng)址和IP主機(jī)地址.
1.IP網(wǎng)址表示網(wǎng)絡(luò)的地址,IP主機(jī)地址表示網(wǎng)絡(luò)中的主機(jī)的地址.->網(wǎng)絡(luò)掩碼用來確認(rèn)IP地址中哪部分是網(wǎng)址,哪部分是主機(jī)地址.
2.網(wǎng)絡(luò)掩碼的限制是前部分都為1,后部分為0.
如假定192.168.3.4的網(wǎng)絡(luò)掩碼是255.255.255.0->則用該掩碼與IP地址進(jìn)行二進(jìn)制與操作->得到的結(jié)果就是IP網(wǎng)址->192.168.3.4的網(wǎng)址是192.168.3.0->網(wǎng)絡(luò)掩碼變?yōu)?55.255.0.0則IP網(wǎng)址則為192.168.0.0.
3.每個網(wǎng)絡(luò)都有IP網(wǎng)址,兩個網(wǎng)絡(luò)之前用路由器連接.
網(wǎng)絡(luò)A <->路由器 網(wǎng)絡(luò)B
網(wǎng)址:192.168.3.0 網(wǎng)址:192.168.4.0
掩碼: 255.255.255.0 掩碼: 255.255.255.0
主機(jī)A:192.168.3.4 主機(jī)C:192.168.4.4
主機(jī)B:192.168.3.5 主機(jī)D:192.168.4.5
4.子網(wǎng)劃分:
1.一個公司可能有一個網(wǎng)址和多個主機(jī)。如網(wǎng)址為192.166.0.0,則可以有2¹6 - 1個主機(jī)加入網(wǎng)中.
2.更好的管理網(wǎng)路->可將網(wǎng)路劃分為多個子網(wǎng).如劃分出192.166.1.0,192.166.2.0,192.166.3.0 3個網(wǎng)址.掩碼都為255.255.255.0.
3.192.166.0.0和192.166.1111.1111有特殊用途,不能作為網(wǎng)絡(luò)中的主機(jī)地址,前者是網(wǎng)絡(luò)地址,后者是廣播地址.(?廣播地址應(yīng)該是192.166.255.255吧?應(yīng)該是8個1吧)
5.發(fā)送數(shù)據(jù)包過程:
1.IP面向包->數(shù)據(jù)被分成若干個小數(shù)據(jù)包->分別傳輸
2.IP網(wǎng)絡(luò)上的主機(jī)只能向本地網(wǎng)上的其他主機(jī),也就是具有相同IP網(wǎng)址的主機(jī)們發(fā)送數(shù)據(jù)包
3.主機(jī)實(shí)際上有兩個不同性質(zhì)的地址:物理地址和IP地址.物理地址是有主機(jī)的網(wǎng)卡標(biāo)識的.物理地址才主機(jī)的真實(shí)地址.
4.主機(jī)A向同一個網(wǎng)絡(luò)的另一個主機(jī)發(fā)包時,會通過地址解析ARP獲得對方的物理地址,然后把包發(fā)給對方.
a.主機(jī)A在網(wǎng)絡(luò)上廣播一個ARP消息,要尋找地址為192.168.3.5的主機(jī)
b.具有這個ip地址的主機(jī)B就會做出響應(yīng),把自身的物理地址告訴主機(jī)A.
(同一個網(wǎng)絡(luò)中,主機(jī)A直接向主機(jī)B發(fā)送IP數(shù)據(jù)包)
5.主機(jī)A向另一個網(wǎng)絡(luò)的主機(jī)B發(fā)送數(shù)據(jù)包時,主機(jī)A利用ARP協(xié)議找到本地網(wǎng)絡(luò)的路由器的物理地址,把包轉(zhuǎn)發(fā)給它.路由器處理步驟:
1.如果數(shù)據(jù)包的生命周期已到,則數(shù)據(jù)包被拋棄.
2.搜索路由表,優(yōu)先搜索路由表中的主機(jī),如果能找到具有目標(biāo)IP地址的主機(jī),則將數(shù)據(jù)包發(fā)送給給主機(jī).
3.匹配主機(jī)失敗,繼續(xù)所有路由表,匹配同子網(wǎng)的路由器.如果找到匹配的路由器,則將數(shù)據(jù)包轉(zhuǎn)發(fā)給該路由器.
4.匹配同子網(wǎng)的路由器失敗,則繼續(xù)搜索路由表,匹配同網(wǎng)絡(luò)的路由器,如果找到,則轉(zhuǎn)發(fā)給該路由.
5.如果以上匹配都失敗,則搜索默認(rèn)路由.如果默認(rèn)路由存在,則按默認(rèn)路由發(fā)送數(shù)據(jù)包,否則丟棄.
->從路由器的處理步驟,IP協(xié)議并不保證一定把數(shù)據(jù)包送達(dá)目標(biāo)主機(jī).在發(fā)送過程匯總,會因?yàn)閿?shù)據(jù)包結(jié)束生命周期,或者找不到路由而丟棄數(shù)據(jù)包.
6.域名
1.IP地址和域名一一對應(yīng).(字符型,記憶方便)
2.從右至左表述意義.最右->頂層域;做左->主機(jī)的機(jī)器名稱;->主機(jī)機(jī)器名.單位名.網(wǎng)絡(luò)名.頂層域名. mail.xyz.edu.cn
3.DNS->采用DNS服務(wù)器提供把域名轉(zhuǎn)換為IP地址.
4.URL:統(tǒng)一資源定位器,標(biāo)識網(wǎng)絡(luò)上資源位置而設(shè)的一種編碼方式.
應(yīng)用層協(xié)議://主機(jī)IP地址或域名/資源所在路徑/文件名 http://www.javathinker.org/bbs/index.jsp
常見的應(yīng)用層協(xié)議還包括ftp和file.
ftp://www.javathinker.org/image
file:///C:\atomcat\webappes\javathinker\admin.jsp
file協(xié)議用于訪問本地計(jì)算機(jī)上的文件,使用這種協(xié)議的URL以"file:///"
7.TCP協(xié)議及端口
1.Ip協(xié)議在發(fā)送數(shù)據(jù)包時->路由器突然崩潰->包丟失|一個包沿低速鏈路,另一個包沿高速鏈路而超過前面的包->包的順序搞亂.
2.TCP協(xié)議使得兩臺主機(jī)的進(jìn)程順利通信->不必?fù)?dān)心包丟失或順序搞亂->TCP根據(jù)包順序,并且在包順序搞亂時按正確順序重組包->包丟失則會請求源主機(jī)重發(fā)包.
3.主機(jī)A的A1進(jìn)程向主機(jī)B的B1進(jìn)程發(fā)送數(shù)據(jù).IP協(xié)議根據(jù)主機(jī)B的ip地址,把A1發(fā)送的數(shù)據(jù)送達(dá)主機(jī)B->TCP決定把數(shù)據(jù)發(fā)送到主機(jī)B的哪個進(jìn)程->TCP采用端口來表示進(jìn)程.->表示進(jìn)程的邏輯地址->表示TCP連接的端點(diǎn)的邏輯地址.
->兩個進(jìn)程進(jìn)行一次通信,就意味建立了一個TCP連接.->B:80->A:1000
->每個進(jìn)程有唯一的地址,TCP就能保證把數(shù)據(jù)順利送到特定的進(jìn)程.
->注:只有進(jìn)程通信的時候采用有端口的概念.
->TCP采用端口來區(qū)分進(jìn)程間的通信
4.C/S模型中,client進(jìn)程可能與服務(wù)器進(jìn)程簡歷多個TCP連接.在client端,每一個TCP連接都會分配一個端口.
5.端口號->0-65535.0-1023的端口號固定分配給一些服務(wù).21-FTP,25-SMTP,80-HTTP,135-RPC;1024到65535的端口號供用戶自定義的服務(wù)使用.->如EchoServer服務(wù)使用8000端口,該程序運(yùn)行時,就會占用8000端口.程序結(jié)束時,就會釋放所占用的端口.
6.客戶端進(jìn)程的端口一般由主機(jī)的os動態(tài)分配->客戶進(jìn)程要求與一個服務(wù)器進(jìn)程進(jìn)行TCP連接時,os會為客戶端進(jìn)程隨機(jī)分配一個還未被占用的端口.當(dāng)client進(jìn)程與server進(jìn)程斷開連接時,這個端口就被釋放.
7.TCP和UDP都用端口來標(biāo)識進(jìn)程的.在一個主機(jī)中,二者端口的取值范圍是各自獨(dú)立的.即允許存在取值相同的TCP端口與UDP端口.
如進(jìn)程A1占用Ftp端口1000,進(jìn)程A2占用UDP端口1000.->這是允許的.
8.RFC
1.TCP/IP協(xié)議是以RFC(Request For Comment)文檔形式發(fā)布的.RFC是描述互聯(lián)網(wǎng)相關(guān)技術(shù)規(guī)范的文檔.
2.每一個文檔有一個RFC編號.
3.http://www.ietf.org/rfc.html
4.輸入http://www.ietf.org/rfc/rfcXXXX.txt.就能查看相關(guān)的RFC文檔,XXX表示文檔編號.如FTP協(xié)議的RFC文檔的網(wǎng)址為
http://www.ietf.org/rfc/rfc959.txt
5.文檔一旦發(fā)布,其編號和內(nèi)容就不允許改變.如果需要更新,則會對更新后的RFC文檔賦予新的編號.
9.C/S通信模式
1.C/S.一個進(jìn)程為客戶進(jìn)程,一個進(jìn)程為服務(wù)器進(jìn)程.->client->request->server->response.
2.一個服務(wù)器進(jìn)程會同時為多個客戶進(jìn)程服務(wù).
3.服務(wù)器進(jìn)程大致工作流程:
while(true)
{
監(jiān)聽端口,等待客戶請求;
響應(yīng)客戶請求;
}
4.EchoServer,用戶自定義的服務(wù).->還有許多通用服務(wù),如HTTP服務(wù)->網(wǎng)絡(luò)應(yīng)用層的協(xié)議規(guī)定了客戶程序與這些通用服務(wù)器程序的通信細(xì)節(jié).->如規(guī)定了Http客戶程序所發(fā)出的請求的格式.還規(guī)定了HTTP服務(wù)器程序發(fā)回的響應(yīng)的格式.
5.現(xiàn)實(shí)中,某些重要的服務(wù)機(jī)構(gòu)的電話是固定的,如110,方便人們記住電話和獲得服務(wù).同樣網(wǎng)絡(luò)上有些通用的服務(wù)用著固定的端口.
FTP 21;TELNET 23;SMTP 25;HTTP 80;POP3 110;IMAP4 143;HTTPS 443;TELNETS 992;IMAPS 993;
10.Java編寫C/S程序
1.本書的Java網(wǎng)絡(luò)程序都建立在TCP/IP協(xié)議基礎(chǔ)上,致力于實(shí)現(xiàn)應(yīng)用層.
2.傳輸層向應(yīng)用層提供了套接字Socket接口.Socket封裝了下層的數(shù)據(jù)傳輸細(xì)節(jié)->應(yīng)用層的程序通過Socket來簡歷與遠(yuǎn)程主機(jī)的連接以及進(jìn)行數(shù)據(jù)傳輸.
3.應(yīng)用層的角度,兩個進(jìn)程之間的一次通信過程從建立連接開始->接著交換數(shù)據(jù)->到斷開連接結(jié)束->套接字可看做是通信線路兩端的收發(fā)器,進(jìn)程通過套接字來收發(fā)數(shù)據(jù).
進(jìn)程A1-Socket<---TCP連接--->Socket-進(jìn)程B1
4.Java中有3中套接字類:Socket/ServerSocket/DatagramSocket.前2建立在TCP協(xié)議基礎(chǔ)上,3建立在UDP協(xié)議基礎(chǔ)上.->Java網(wǎng)絡(luò)程序都采用C/S通信模式.
部分源代碼
package com.game.landon.entrance;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


/** *//**
*
*從控制臺讀取輸入字符串,并echo:XX
*<p>輸入bye,則結(jié)束程序</p>
*
*@author landon
*@since 1.6.0_35
*@version 1.0.0 2013-5-27
*
*/

public class EchoPlayer


{
public String echo(String msg)

{
return "echo:" + msg;
}
public void talk() throws IOException

{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String msg = null;
while((msg = br.readLine()) != null)

{
System.out.println(echo(msg));
if("bye".equals(msg))

{
break;
}
}
}
public static void main(String[] args) throws IOException

{
EchoPlayer echoPlayer = new EchoPlayer();
echoPlayer.talk();
}
}

package com.game.landon.entrance;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;


/** *//**
*
*A Easy Echo Client
*
*@author landon
*@since 1.6.0_35
*@version 1.0.0 2012-9-27
*
*/

public class EchoClient


{
private String host = "localhost";
private int port = 8000;
private Socket socket;
public EchoClient() throws IOException

{
//connect to the server with specified host and port
//os為客戶的每個連接分配一個唯一的端口
//客戶進(jìn)程中,Socket對象包含了本地及對方服務(wù)進(jìn)程的端口信息.在服務(wù)器進(jìn)程中,Socket對象也包含了本地以及對方客戶進(jìn)程的地址和端口信息.
//客戶進(jìn)程允許建立多個連接,每個連接都有唯一的端口
//編寫網(wǎng)絡(luò)程序時,一般只需顯示的為服務(wù)器程序中的ServerSocket設(shè)置端口,而不必考慮客戶程序所用的端口
socket = new Socket(host,port);
}

/** *//**
* Wrapped {@link Socket#getOutputStream()} to PrintWriter
* @param socket
* @return
* @throws IOException
*/
private PrintWriter getWriter(Socket socket) throws IOException

{
OutputStream socketOut = socket.getOutputStream();
//public PrintWriter(OutputStream out, boolean autoFlush)
return new PrintWriter(socketOut,true);
}

/** *//**
* Wrapped {@link Socket#getInputStream()} to BufferedReader
* @param socket
* @return
* @throws IOException
*/
private BufferedReader getReader(Socket socket) throws IOException

{
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}

/** *//**
*
* talk to echo server
*
* @throws IOException
*/
public void talk() throws IOException

{
try

{
//與Echo Server通信用的到包裝后的reader和writer
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
//本地reader,用來從system.in,即控制臺輸入數(shù)據(jù)
BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
String msg = null;
while((msg = localReader.readLine()) != null)

{
//向server輸出消息
pw.println(msg);
//從server讀取消息
System.out.println(br.readLine());
if("bye".equals(msg))

{
break;
}
}
}
catch(IOException e)

{
e.printStackTrace();
}
finally

{
try

{
socket.close();
}
catch(IOException e)

{
e.printStackTrace();
}
}
}
public static void main(String
args) throws IOException

{
new EchoClient().talk();
}
}

package com.game.landon.entrance;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;


/** *//**
*
*A Easy Echo Server
*<p>
*1.當(dāng)前這個EchoServer的問題是只能連接一個Client,只有當(dāng)前的client輸入bye,結(jié)束連接的時候,才會處理下一個client
*2.原因在于service方法,while(br.readLine() != null),這里,當(dāng)Client沒有輸入數(shù)據(jù)時,線程則掛起,阻塞,等待client輸入
*</p>
*
*@author landon
*@since 1.6.0_35
*@version 1.0.0 2012-9-27
*
*/

public class EchoServer


{
private int port = 8000;
private ServerSocket serverSocket;
public EchoServer() throws IOException

{
//ServerSocket
// 構(gòu)造方法負(fù)責(zé)在os中把當(dāng)前進(jìn)程注冊為服務(wù)器進(jìn)程,監(jiān)聽port端口
serverSocket = new ServerSocket(port);
System.out.println("Echo Server Launched!");
}

/** *//**
* echo to client
* @param msg
* @return
*/
public String echo(String msg)

{
return "echo:" + msg;
}

/** *//**
* Wrapped {@link Socket#getOutputStream()} to PrintWriter
* @param socket
* @return
* @throws IOException
*/
private PrintWriter getWriter(Socket socket) throws IOException

{
// 返回輸出流對象,向輸出流寫數(shù)據(jù),就能向?qū)Ψ桨l(fā)送數(shù)據(jù)
OutputStream socketOut = socket.getOutputStream();
//public PrintWriter(OutputStream out, boolean autoFlush)
return new PrintWriter(socketOut,true);
}

/** *//**
* Wrapped {@link Socket#getInputStream()} to BufferedReader
* @param socket
* @return
* @throws IOException
*/
private BufferedReader getReader(Socket socket) throws IOException

{
// 返回輸入流對象;只需從輸入流讀數(shù)據(jù),就能接收來自對方的數(shù)據(jù)
InputStream socketIn = socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn));
}

/** *//**
* Echo Server main Logic Service
*/
public void service()

{
//while true loop to wait client connect
while(true)

{
Socket socket = null;
try

{
//accept client socket
// 監(jiān)聽端口,等待客戶的連接請求,如果接收到一個連接請求,該方法返回一個Socket對象.該Socket對象與客戶端的Socket對象形成了一條通信線路
//該Socket對象包含了客戶的地址和端口信息.EchoClient作為客戶程序,它的端口是由os隨機(jī)產(chǎn)生的.每當(dāng)客戶程序創(chuàng)建一個Socket對象時,os就會客戶分配一個端口
socket = serverSocket.accept();
System.out.println("New Connection accepted:" + socket.getInetAddress() + ":" + socket.getPort());
BufferedReader br = getReader(socket);
PrintWriter pw = getWriter(socket);
String msg = null;
//read from client
while((msg = br.readLine()) != null)

{
System.out.println(msg);
//write to client
pw.println(echo(msg));
if(msg.equals("bye"))

{
break;
}
}
}
catch(IOException e)

{
e.printStackTrace();
}
finally

{
try

{
if(socket != null)

{
//close socket
socket.close();
}
}
catch(IOException e)

{
e.printStackTrace();
}
}
}
}
public static void main(String
args) throws IOException

{
//launch echo_server
new EchoServer().service();
}
}

posted on 2013-07-02 15:32
landon 閱讀(2420)
評論(0) 編輯 收藏 所屬分類:
Program