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

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


/** *//**
*
*從控制臺讀取輸入字符串,并echo:XX
*<p>輸入bye,則結束程序</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為客戶的每個連接分配一個唯一的端口
//客戶進程中,Socket對象包含了本地及對方服務進程的端口信息.在服務器進程中,Socket對象也包含了本地以及對方客戶進程的地址和端口信息.
//客戶進程允許建立多個連接,每個連接都有唯一的端口
//編寫網絡程序時,一般只需顯示的為服務器程序中的ServerSocket設置端口,而不必考慮客戶程序所用的端口
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,即控制臺輸入數據
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.當前這個EchoServer的問題是只能連接一個Client,只有當前的client輸入bye,結束連接的時候,才會處理下一個client
*2.原因在于service方法,while(br.readLine() != null),這里,當Client沒有輸入數據時,線程則掛起,阻塞,等待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
// 構造方法負責在os中把當前進程注冊為服務器進程,監聽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

{
// 返回輸出流對象,向輸出流寫數據,就能向對方發送數據
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));
}

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

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

{
Socket socket = null;
try

{
//accept client socket
// 監聽端口,等待客戶的連接請求,如果接收到一個連接請求,該方法返回一個Socket對象.該Socket對象與客戶端的Socket對象形成了一條通信線路
//該Socket對象包含了客戶的地址和端口信息.EchoClient作為客戶程序,它的端口是由os隨機產生的.每當客戶程序創建一個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 閱讀(2414)
評論(0) 編輯 收藏 所屬分類:
Program