http://i-lolo.iteye.com/blog/1611562
在進入網絡通信之前,讓我們來普及一點網絡基礎概念。如果你是有一定的計算機網絡基礎,請直接跳到第五點之后開始閱讀。
第一、 什么是計算機網絡?
書本上那些文縐縐的概念我們可以不去理,我告訴你,我們兩臺電腦連在一起就組成了一個計算機網絡。其實我們的電腦甚至是全世界的電腦都是連著的,只要你的電腦連著網,你就在這個巨大的計算機網絡里,你也許會問為什么我和他們是連著的啊?大家知道自己是怎么上的網?ADSL是吧,撥號上網。換個比方說吧,我們在公司我們的電腦通過網線,雙絞線,然后是Hub(集線器),連接到胡哥的電腦,然后胡哥的機子通過撥號,ADSL,連到電信的網關那兒,然后中國電信通過海底光纜和美國電信網關連接,然后再像剛剛我們連接中國電信一樣,逆推過去,連接到美國每一臺聯網的計算機。所以說只要你連著網,你就是和全世界的在線用戶連著。這是一個巨大的計算機網絡。非常巨大。
第二、 計算機網絡的主要功能?
資源共享、信息傳輸與集中處理、均衡負荷與分布處理、綜合信息服務(www/綜合數字網絡 ISDN)。這些個功能,不多說。這些你不平時都在用么?你的資源能夠上傳共享給其他人,有的人平時還很喜歡聊QQ,是吧,所以上面說的這四個也許還有更多的什么功能都是些冠冕堂皇的話,稍微看下就好。用了自然就曉得了。
第三、 什么是網絡通信協議?
我來問你,為什么你說話身邊的人能夠聽的懂,別人說的話你為什么也能夠聽懂,而為什么如果你去對一個外國人說話或者一個外國人來和你說話你們卻互相聽不懂呢?你會說廢話嘛因為我說的是中文,是漢語,中國人說的都是漢語,而外國人說的是另一種語言,是外語。就是這樣,網絡通信協議就像我們的中文一樣,她就是我們之間的共同語言,他規定了我們之間怎么說話,我先說什么你再說什么,你怎么說,而我應該怎么聽。而網絡通信得先規定約定一些俗成的網絡通信協議,先說好,兩臺計算機之間什么收發信息,信息格式是什么,信息怎么發,怎么接收,而萬一出錯怎么辦怎么處理。沒有了這個協議,兩臺電腦就不知道互相之間怎么說話,就像你對一頭大母豬說完愛你,而人家根本就不知道你在說什么。
在這兒和大家提一下網絡協議的分層思想。學過計算機網絡的同學都知道有兩種基本的國際標準分層模型,一個是OSI參考模型,一個是TCP/IP參考模型。OSI參考模型,是國際標準化組織搞出來的開放互聯傳統模型,一共有七層:物理/數據鏈路/網絡/傳輸/會話/表示/應用。學網絡和硬件的一般都要熟悉這七層標準,至于這七層都是干嘛的,大家自己問度娘或者自己看關于網絡的書去。(中南大學高陽教授主編了一本叫《計算機網絡原理與實用技術》的書,里邊很詳盡的介紹了這個OSI參考模型,沒記錯的話應該是在第一章1.4.5里,是放在TCP/IP協議之后的……)這里就不多說了,因為對于咱們編程的軟件人員來說,實際當中的應用,是分為四層,也就是TCP/IP參考模型。最底層物理+數據鏈路層/網絡層/傳輸層/應用層。我們編的程序是位于應用層,所以說,我們一直是在和哪一層打交道?TCP/IP層。我們編寫一個程序發送一些數據,發給傳輸層,TCP/IP層,在這一層對數據進行封裝,按照先前約定的協議,然后走向下一層,通過網線,再走到物理數據鏈路層,這時候數據就變成了一連串的01010101,到達對面之后逆推上面的過程,進行解封,ok,信息發送完畢。這兒涉及到比較多的網絡底層,目前我們不需要過多了解,因為我們要做的工作不需要了解牽扯到到這么底層的東西,如果你想深入了解或者今后你想做殺毒軟件什么的,去讀《TCP/IP詳解》。
第四、 IP——(Internet Protocol網絡之間互連的協議)?
你不用管其他的,你只需要知道IP這個東西給我們做出的最大貢獻,就是給我們每一臺電腦提供了一個獨一無二的IP地址。你想我的機器要和你的機器交流說話,我得知道你的機器叫什么,你的機器得有一個獨一無二的區別標識,否則的話我就不知道傳的信息有沒有傳到你那兒,也不知道這信息到底傳給誰。IP地址這東西我們都知道吧?像我的本機IP: 113.240.187.242 這是湖南省長沙市的IP。他是由四個字節組成的(也就是說每一個值不能超過255)。(這個是IPV4,能夠組成將近四億多地址,現在已經出來了IPV6,高檔貨,八個字節,地址數是IPV4的幾何倍數)IPV4的IP地址按照其網絡IP段和主機IP段占的字節數分ABC三類網。這個這里不說,大家自己去了解,好吧?拿高陽教授的那本書翻翻。順帶看看子網掩碼啊網關啊什么的。自己去了解。在這兒我就累得給你敲了。
第五、 TCP協議和UDP協議?
好了,上一步里我們通過獨一無二的IP地址找到了對方連在了一起。我們可以通話了,關于通話我們有兩種方式:
第一、 TCP協議,什么叫TCP協議?Transmission Control Protocol 傳輸控制協議TCP是一種面向連接(連接導向)的、可靠的、基于字節流的運輸層(Transport layer)通信協議。什么叫可靠的?打個比方,我們打電話,上一步通過IP找到對方就相當于撥號打通了你的電話,你拿起電話接了,我說一句“喂?”,如果你這邊不回應,我就會杵這兒一直“喂”下去,是不?因為不知道你那邊到底接到了聽到了我的話沒有,所以你這邊一定要告訴我你聽到了你收到了我剛剛的那句信息,我才會接著給你說下面的話給你發下面的數據。我每發一次信息我要你給我確認收到了,然后我再給你發接下來的東西,這個就叫可靠。在TCP/IP協議里邊這叫“三次握手”機制。怎么握手,握手是怎么回事,問度娘,好吧?
第二、 UDP協議。User Datagram Protocol的簡稱, 中文名是用戶數據報協議,是 OSI 參考模型中一種無連接的傳輸層協議。UDP這種方式相對于TCP來說更加簡單。UDP說話就是,我給你說一句話,你聽沒聽到我不管。就像發電報,“黃河黃河我是長江!”哐當一下就發出去了。不管黃河收到沒有。兩種方式一種安全可靠但是慢,一種簡單快捷但是不可靠。根據不同的需求選擇。像我們平時聊QQ開視頻啊什么的,用的就是UDP,因為我們傳輸的這些個數據丟個一兩個包什么的無所謂,頂多就是視頻多了幾個馬賽克,是吧。那么平時我們玩的網絡游戲,像CF啊魔獸世界啊,是哪一種呢?自己想,好吧?
第三、 中南-馬志丹 http://java-mzd.javaeye.com 驚喜看得到!
基礎普及完了,接下來我們來看看為什么要去做網絡通信。這一段我就簡單點說。在計算機剛出來那會兒 ,那時候的人們都覺得計算機這東西就是主要為計算而存在的就是一個計算工具,但是自從1983年起,TCP\IP協議的出現,讓計算機從此轉變為了人們的一個交流工具。自那以后,只要你有一臺電腦,不管你是開網頁看電影,還是上人人找朋友,不管你是登郵箱收發郵件,還是登QQ聊天,你的生活的方方面面都離不開那電腦屏幕后邊的網絡技術。換句話說,如果沒有了網絡通信技術,電腦以及大多數軟件將會失去他們原有的生命力。就像一棵大樹沒有根。沒有網絡通信就沒有如今繁榮的QQ世界,沒有了網絡通信,世界上那些個IT巨頭諸如IBM諸如谷歌,將會如斷線風箏落日殘陽。我想說,如果你不懂網絡通信技術,你就不是一個合格的程序員,如果你不精通網絡通信技術,你就無法開發出一款真正優秀的營運軟件!除非你想永遠停留在枯燥的單機時代,你想讓自己的技術永遠留在表層。
現在,讓我們來考慮如何實現。
在做實現之前,我想先讓大家明白幾個概念:
1) Socket
A. 兩個Java應用程序可通過一個雙向的網絡通信連接實現數據交換,這個雙向鏈路的一端稱為一個Socket
B. Socket通常用來實現client-server連接
C. Java.net包中定義的兩個類Socket和ServerSocket,分別用來實現雙向連接的client和server端
D. 建立連接時所需要的尋址信息為遠程計算機的IP地址和端口號(Port number)
上面我們提到了IP地址,那是每一臺電腦獨一無二的一個地址標識,是為了對方計算機能夠找得到你給你發信息。建立連接我們很顯然需要這個信息才能夠完成。那么這個端口號又是用來干什么的呢?舉個例子,假如說我電腦上現在上著人人和QQ,你的電腦上也是上著人人和QQ,如果我用QQ給你發一條消息他怎么知道就發到你的QQ上而不會在你的人人上呢?是吧?所以說光用IP地址是無法區分到不同的應用程序的。所以需要端口號來達到這個作用。端口號在計算機內部是用兩個字節來表示,也就是說總共有65536個端口。在這兒需要注意下面兩個點:
?1.1024之前的端口我們自己編的程序不要征用它,因為這些端口是給系統用的。比如說80端口,胡哥給咱們講過的。干嘛的?負責處理HTTP上網訪問網頁等等的端口。還有就是21端口,FTP的,是吧?還有其他的一些著名端口,想知道問度娘去,好吧?在這里就不羅嗦了。
?2.TCP端口和UDP端口是分開的,比如說TCP有個8888端口,他和你的UDP8888端口是不一樣的。
?3.上述每一類有65536個端口。也就是說我們的計算機能夠運行131072個程序,只要你電腦吃得消。
既然要實現通信,那我們肯定要確定兩個通信對象,一個是服務器對象server,一個是客戶端對象client。我們需要知道,這兩個對象是兩個應用程序,他們的對話,是兩個不同的程序之間的對話。你會說我只有兩個對象也還沒法實現他們之間的交互啊,不用急,我也知道他們兩個不是神仙會心有靈犀。兩個對象之間想要實現互相之間的信息交互,就必須要有一個通道。這個通道就像是一根管子,一頭扎在服務器端,一頭插在客戶端。信息就在這根管子里來來往往。這根管子怎么插呢,插在哪兒呢?這個時候就需要用到剛剛提到的Socket了。
Socket的意思呢就是一個插座,服務器和客戶端各有一個插座,安插在各自的一個端口上,管子插在這兩個插座上,然后在他們這兩個端口上接入數據流。Socket通常用來實現server-client連接。Java里面有一個包java.net,他下邊有定義了兩個類,Socket和ServerSocket,分別用來實現雙向連接的server端和client端。
接下來我們來建立TCP服務器端和客戶端。
服務器端:我們用的是ServerSocket,新建一個server插座,并且交給他一個端口號,這個插座他有一個非常方便的構造方法ServerSocket(int port),讓他知道自己監聽哪一個端口,然后新建一個socket對象,開機,并用.accept語句讓他處在待機狀態,等待接受client的接入。一旦有客戶端接入就將它賦給新建的Socket對象,并且用.getInputStream以及.getOutputStream命令獲得他的輸入輸出流。這個流,就是一根管子,信息都在這根管子里流通。這樣說東西不怎么好說,那么我們就在這個流上面再包一層,將這個流封裝成DataOutputStream(),DataInputStream。然后就可以利用輸出流(這個是相對于服務器來說,這個輸出流到了客戶端就成了輸入流了)來.write信息,利用輸入流來.read()獲取客戶端發來的信息。Ok,接收完了,.close關閉輸入輸出流,以及關閉socket,關機。
客戶端:寫法和服務器端有點類似,新建一個插座,這兒需要留意的是,客戶端需要用到的插座是Socket而不是ServerSocket,新建一個Socket牌插座,同樣用他的Socket(String host,int port)構造方法方法給他一個IP地址和端口號,讓它撥打區號以及具體電話號,這個和服務器端的IP地址以及端口號要一致,ok,這個時候server就相當于申請連接到服務器的某一個端口上了。兩個程序就等于是連接上了。但是有些人就會問了啊,這只是客戶端申請連接,人家服務器接不接受呢。好,前面我們的服務器不是提到了.accept么,這個方法就是用來接受客戶端的,這個時候就是:你申請連接,我接受連接,接下來,照著上面服務器一樣,客戶端也獲取到自己的輸入輸出流,封裝,用輸出流寫出信息。咱們之間就可以互相通信了。還有一個問題啊,要是如果有另一個客戶端接入了呢?簡單,那就再.accept一下。如果有N多客戶端接入,那就不斷的.accept,不斷循環它。這個問題大家都知道可以用while語句。
具體的敲法,請看我給大家附上的代碼實現。下面給大家看下Socket通信模型。看著這個模型,再回頭看看上面給大家嘮叨的那些個點,我想大家都知道服務器和客戶端該怎么去寫怎么去實現通信了吧?
好了,這一段“三分鐘讓你看懂”到此就結束了,想來大家對網絡通信也該有了一個相對清晰的認識。如果你還想了解學習更多的網絡通信方面的知識,如果你還想知道如何去實現一些更多的通信功能,比如建立公共聊天室實現群聊,又比如建立一個以互聯網為基礎的以網絡畫板為主體的協助平臺,又比如,你想做一個自己的軟件來實現像QQ一樣MSN一樣或者像人人桌面一樣的各種功能……請繼續關注我們的隨后更新。請記住,我們是ZCL,我們是一群簡單快樂的牧碼人!
后記:第一篇正兒八經的技術日志,4K多全手打,這樣說起來應該蠻自豪的感覺。但是說實話還是覺得自己寫的有些亂。自己只是把課堂上老師們講的一些知識點,根據自己敲的代碼以及做了的一些課堂筆記,羅列了出來。也查了一些在線資料和書籍,像度娘,像學校發的那本我都沒怎么動過的《計算機網絡原理和實用技術》。在前面花了好些篇幅來講計算機網絡基礎知識,是因為我給自己定下的目標就是讓任何一個人甚至你是沒怎么學過接觸過java或者計算機網絡這一塊,看了我的博客之后,都能夠對網絡通信有一個比較清晰的認識,而讓接觸過java的人知道怎么樣初步的去實現兩個軟件或者說程序之間的通信,知道他們之間是怎么回事兒并且自己動手實現它。這確實是一個有點難度的過程。但是你如果把這個都搞定了,那么,你的java網絡通信就基本可以說入了一個門了。我似乎聽見了胡哥用他那一慣的口吻在我身后說,這種程度,要說入門還早的很呢!當然咯,就算我現在做到網絡畫圖板做到網絡文件傳輸,也感覺自己只是進了一個門,門后的世界無比之大,等待我們不斷的去探索,去創新,去創造它。生命有限,學海無涯;人有老時,學無止境嘛。發現的問題蠻多。但獲得的收獲也不少。果然檢驗自己是否學會掌握一個東西的最好辦法就是嘗試著去教給別人。只有你能夠很清晰的把事兒給別人說清楚了教會了,你才能說自己懂了。寫完這篇博客,感覺自己對網絡通信的理解又加深了一些,對其中的一些知識點的掌握也更加牢靠了一些。只言片語薄聞淺見,希望大家多多批評不吝賜教!
最后的最后:用胡哥的一句話來與君共勉吧!
標準即平庸,合格即廢物。
(附)服務器端代碼:
Java代碼 收藏代碼
package con120722;
import java.net.*;
import java.io.*;
public class Server
{
private ServerSocket ss;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Server()
{
try
{
ss = new ServerSocket(10000);
while (true)
{
socket = ss.accept();
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
String line = in.readLine();
out.println("you input is :" + line);
out.close();
in.close();
socket.close();
}
}
catch (IOException e)
{}
}
public static void main(String[] args)
{
new Server();
}
}
客戶端代碼:
Java代碼 收藏代碼
package con120722;
Java代碼 收藏代碼
import java.io.*;
import java.net.*;
public class Client
{
Socket socket;
BufferedReader in;
PrintWriter out;
public Client()
{
try
{
socket = new Socket("localhost", 10000);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(),true);
BufferedReader line = new BufferedReader(new InputStreamReader(System.in));
out.println(line.readLine());
line.close();
out.close();
in.close();
socket.close();
}
catch (IOException e)
{}
}
public static void main(String[] args)
{
new Client();
}
}