日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java程序员从笨鸟到菜鸟之(十三)java网络通信编程

發(fā)布時(shí)間:2025/3/21 java 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java程序员从笨鸟到菜鸟之(十三)java网络通信编程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先聲明一下,剛開始學(xué)習(xí)Java網(wǎng)絡(luò)通信編程就對他有一種畏懼感,因?yàn)樽约簩W(wǎng)絡(luò)一竅不通,所以。。。呵呵。。你懂得,昨天又仔細(xì)的學(xué)習(xí)了一遍,感覺其實(shí)java網(wǎng)絡(luò)編程也沒想象的那么難,不信,咱一起看看。。。呵呵。。

?????網(wǎng)絡(luò)編程就是在兩個(gè)或兩個(gè)以上的設(shè)備(例如計(jì)算機(jī))之間傳輸數(shù)據(jù)。程序員所作的事情就是把數(shù)據(jù)發(fā)送到指定的位置,或者接收到指定的數(shù)據(jù),這個(gè)就是狹義的網(wǎng)絡(luò)編程范疇。在發(fā)送和接收數(shù)據(jù)時(shí),大部分的程序設(shè)計(jì)語言都設(shè)計(jì)了專門的API實(shí)現(xiàn)這些功能,程序員只需要調(diào)用即可。所以,基礎(chǔ)的網(wǎng)絡(luò)編程可以和打電話一樣簡單

一:首先看一下網(wǎng)絡(luò)通訊的兩種方式

1.TCP(傳輸控制協(xié)議)方式

TCP方式就類似于撥打電話,使用該種方式進(jìn)行網(wǎng)絡(luò)通訊時(shí),需要建立專門的虛擬連接,然后進(jìn)行可靠的數(shù)據(jù)傳輸,如果數(shù)據(jù)發(fā)送失敗,則客戶端會(huì)自動(dòng)重發(fā)該數(shù)據(jù)

2.?UDP(用戶數(shù)據(jù)報(bào)協(xié)議)方式

?????UDP方式就類似于發(fā)送短信,使用這種方式進(jìn)行網(wǎng)絡(luò)通訊時(shí),不需要建立專門的虛擬連接,傳輸也不是很可靠,如果發(fā)送失敗則客戶端無法獲得

?這兩種傳輸方式都是實(shí)際的網(wǎng)絡(luò)編程中進(jìn)行使用,重要的數(shù)據(jù)一般使用TCP方式進(jìn)行數(shù)據(jù)傳輸,而大量的非核心數(shù)據(jù)則都通過UDP方式進(jìn)行傳遞,在一些程序中甚至結(jié)合使用這兩種方式進(jìn)行數(shù)據(jù)的傳遞。由于TCP需要建立專用的虛擬連接以及確認(rèn)傳輸是否正確,所以使用TCP方式的速度稍微慢一些,而且傳輸時(shí)產(chǎn)生的數(shù)據(jù)量要比UDP稍微大一些。

總結(jié)一下UDPTCP協(xié)議的區(qū)別

-使用UDP時(shí),每個(gè)數(shù)據(jù)報(bào)中都給出了完整的地址信息,因此無需要建立發(fā)送方和接收方的連接。?

–對于TCP協(xié)議,由于它是一個(gè)面向連接的協(xié)議,在socket之間進(jìn)行數(shù)據(jù)傳輸之前必然要建立連接,所以在TCP中多了一個(gè)連接建立的時(shí)間?

–使用UDP傳輸數(shù)據(jù)時(shí)是有大小限制的,每個(gè)被傳輸?shù)臄?shù)據(jù)報(bào)必須限定在64KB之內(nèi)。?

–TCP沒有這方面的限制,一旦連接建立起來,雙方的socket就可以按統(tǒng)一的格式傳輸大量的數(shù)據(jù)。?

–UDP是一個(gè)不可靠的協(xié)議,發(fā)送方所發(fā)送的數(shù)據(jù)報(bào)并不一定以相同的次序到達(dá)接收方。?

–TCP是一個(gè)可靠的協(xié)議,它確保接收方完全正確地獲取發(fā)送方所發(fā)送的全部數(shù)據(jù)?

-TCP在網(wǎng)絡(luò)通信上有極強(qiáng)的生命力,例如遠(yuǎn)程連接(Telnet)和文件傳輸(FTP)都需要不定長度的數(shù)據(jù)被可靠地傳輸。?

—相比之下UDP操作簡單,而且僅需要較少的監(jiān)護(hù),因此通常用于局域網(wǎng)高可靠性的分散系統(tǒng)中client/server應(yīng)用程序?

二:基于url的網(wǎng)絡(luò)編程

1.創(chuàng)建一個(gè)URL

為了表示URL,?java.Net中實(shí)現(xiàn)了類URL。我們可以通過下面的構(gòu)造方法來初始化一個(gè)URL對象:
  
(1)?public?URL?(String?spec);
     通過一個(gè)表示URL地址的字符串可以構(gòu)造一個(gè)URL對象
     URL?urlBase=new?URL("http://www.?263.net/")
?  (2)?public?URL(URL?context,?String?spec);
     通過基URL和相對URL構(gòu)造一個(gè)URL對象。
     URL?net263=new?URL?("http://www.263.net/");
     URL?index263=new?URL(net263,?"index.html")
  (3)?public?URL(String?protocol,?String?host,?String?file);
     new?URL("http",?"www.gamelan.com",?"/pages/Gamelan.net.?html");
  (4)?public?URL(String?protocol,?String?host,?int?port,?String?file);
     URL?gamelan=new?URL("http",?"www.gamelan.com",?80,?"Pages/Gamelan.network.html");

  注意:類URL的構(gòu)造方法都聲明拋棄非運(yùn)行時(shí)例外(MalformedURLException),因此生成URL對象時(shí),我們必須要對這一例外進(jìn)行處理,通常是用try-catch語句進(jìn)行捕獲。格式如下:

try{
     URL?myURL=?new?URL()
  }catch?(MalformedURLException?e){
  …  }

2.?解析一個(gè)URL

一個(gè)URL對象生成后,其屬性是不能被改變的,但是我們可以通過類URL所提供的方法來獲取這些屬性:
   public?String?getProtocol()?獲取該URL的協(xié)議名。
   public?String?getHost()?獲取該URL的主機(jī)名。
   public?int?getPort()?獲取該URL的端口號,如果沒有設(shè)置端口,返回-1。
   public?String?getFile()?獲取該URL的文件名。
   public?String?getRef()?獲取該URL在文件中的相對位置。
   public?String?getQuery()?獲取該URL的查詢信息。
   public?String?getPath()?獲取該URL的路徑
  ??public?String?getAuthority()?獲取該URL的權(quán)限信息
   public?String?getUserInfo()?獲得使用者的信息
   ?public?String?getRef()獲得該URL的錨

3.從URL讀取WWW網(wǎng)絡(luò)資源

當(dāng)我們得到一個(gè)URL對象后,就可以通過它讀取指定的WWW資源。這時(shí)我們將使用URL的方法openStream(),其定義為:
InputStream?openStream();
  
  方法openSteam()與指定的URL建立連接并返回InputStream類的對象以從這一連接中讀取數(shù)據(jù)。
URL?url?=?new?URL("http://www.baidu.com");

//使用openStream得到一輸入流并由此構(gòu)造一個(gè)BufferedReader對象

BufferedReader?br?=?new?BufferedReader(new?InputStreamReader( url.openStream()));

String?line?=?null;

while(null?!=?(line?=?br.readLine()))

{

System.out.println(line);

}

br.close();

三:客戶端網(wǎng)絡(luò)編程步驟

按照前面的基礎(chǔ)知識(shí)介紹,無論使用TCP方式還是UDP方式進(jìn)行網(wǎng)絡(luò)通訊,網(wǎng)絡(luò)編程都是由客戶端和服務(wù)器端組成

1.客戶端網(wǎng)絡(luò)編程步驟

????????客戶端(Client)是指網(wǎng)絡(luò)編程中首先發(fā)起連接的程序,客戶端一般實(shí)現(xiàn)程序界面和基本邏輯實(shí)現(xiàn),在進(jìn)行實(shí)際的客戶端編程時(shí),無論客戶端復(fù)雜還是簡單,以及客戶端實(shí)現(xiàn)的方式,客戶端的編程主要由三個(gè)步驟實(shí)現(xiàn):

1、?建立網(wǎng)絡(luò)連接

客戶端網(wǎng)絡(luò)編程的第一步都是建立網(wǎng)絡(luò)連接。在建立網(wǎng)絡(luò)連接時(shí)需要指定連接到的服務(wù)器的IP地址和端口號,建立完成以后,會(huì)形成一條虛擬的連接,后續(xù)的操作就可以通過該連接實(shí)現(xiàn)數(shù)據(jù)交換了。

2、?交換數(shù)據(jù)

連接建立以后,就可以通過這個(gè)連接交換數(shù)據(jù)了。交換數(shù)據(jù)嚴(yán)格按照請求響應(yīng)模型進(jìn)行,由客戶端發(fā)送一個(gè)請求數(shù)據(jù)到服務(wù)器,服務(wù)器反饋一個(gè)響應(yīng)數(shù)據(jù)給客戶端,如果客戶端不發(fā)送請求則服務(wù)器端就不響應(yīng)。

根據(jù)邏輯需要,可以多次交換數(shù)據(jù),但是還是必須遵循請求響應(yīng)模型。

3、?關(guān)閉網(wǎng)絡(luò)連接

在數(shù)據(jù)交換完成以后,關(guān)閉網(wǎng)絡(luò)連接,釋放程序占用的端口、內(nèi)存等系統(tǒng)資源,結(jié)束網(wǎng)絡(luò)編程。

????????最基本的步驟一般都是這三個(gè)步驟,在實(shí)際實(shí)現(xiàn)時(shí),步驟2會(huì)出現(xiàn)重復(fù),在進(jìn)行代碼組織時(shí),由于網(wǎng)絡(luò)編程是比較耗時(shí)的操作,所以一般開啟專門的現(xiàn)場進(jìn)行網(wǎng)絡(luò)通訊。

2.服務(wù)器端網(wǎng)絡(luò)編程步驟

????????服務(wù)器端(Server)是指在網(wǎng)絡(luò)編程中被動(dòng)等待連接的程序,服務(wù)器端一般實(shí)現(xiàn)程序的核心邏輯以及數(shù)據(jù)存儲(chǔ)等核心功能。服務(wù)器端的編程步驟和客戶端不同,是由四個(gè)步驟實(shí)現(xiàn),依次是:

1、?監(jiān)聽端口

服務(wù)器端屬于被動(dòng)等待連接,所以服務(wù)器端啟動(dòng)以后,不需要發(fā)起連接,而只需要監(jiān)聽本地計(jì)算機(jī)的某個(gè)固定端口即可。

這個(gè)端口就是服務(wù)器端開放給客戶端的端口,服務(wù)器端程序運(yùn)行的本地計(jì)算機(jī)的IP地址就是服務(wù)器端程序的IP地址。

2、?獲得連接

當(dāng)客戶端連接到服務(wù)器端時(shí),服務(wù)器端就可以獲得一個(gè)連接,這個(gè)連接包含客戶端的信息,例如客戶端IP地址等等,服務(wù)器端和客戶端也通過該連接進(jìn)行數(shù)據(jù)交換。

一般在服務(wù)器端編程中,當(dāng)獲得連接時(shí),需要開啟專門的線程處理該連接,每個(gè)連接都由獨(dú)立的線程實(shí)現(xiàn)。

3、?交換數(shù)據(jù)

服務(wù)器端通過獲得的連接進(jìn)行數(shù)據(jù)交換。服務(wù)器端的數(shù)據(jù)交換步驟是首先接收客戶端發(fā)送過來的數(shù)據(jù),然后進(jìn)行邏輯處理,再把處理以后的結(jié)果數(shù)據(jù)發(fā)送給客戶端。簡單來說,就是先接收再發(fā)送,這個(gè)和客戶端的數(shù)據(jù)交換數(shù)序不同。

其實(shí),服務(wù)器端獲得的連接和客戶端連接是一樣的,只是數(shù)據(jù)交換的步驟不同。

當(dāng)然,服務(wù)器端的數(shù)據(jù)交換也是可以多次進(jìn)行的。

在數(shù)據(jù)交換完成以后,關(guān)閉和客戶端的連接。

4、?關(guān)閉連接

當(dāng)服務(wù)器程序關(guān)閉時(shí),需要關(guān)閉服務(wù)器端,通過關(guān)閉服務(wù)器端使得服務(wù)器監(jiān)聽的端口以及占用的內(nèi)存可以釋放出來,實(shí)現(xiàn)了連接的關(guān)閉。

四:一個(gè)基礎(chǔ)的網(wǎng)絡(luò)類——InetAddress類

????該類的功能是代表一個(gè)IP地址,并且將IP地址和域名相關(guān)的操作方法包含在該類的內(nèi)部。

????關(guān)于該類的使用,下面通過一個(gè)基礎(chǔ)的代碼示例演示該類的使用,代碼如下:

[java]?view plaincopy print?
  • <span?style="BACKGROUND-COLOR:?#333333">public?class?InetAddressDemo?{??
  • ??
  • public?static?void?main(String[]?args)?{??
  • ??
  • try?{??
  • ??
  • //?使用域名創(chuàng)建對象??
  • ??
  • InetAddress?inet1?=?InetAddress.getByName("www.163.com");??
  • ??
  • System.out.println(inet1);??
  • ??
  • //?使用IP創(chuàng)建對象??
  • ??
  • InetAddress?inet2?=?InetAddress.getByName("127.0.0.1");??
  • ??
  • System.out.println(inet2);??
  • ??
  • //?獲得本機(jī)地址對象??
  • ??
  • InetAddress?inet3?=?InetAddress.getLocalHost();??
  • ??
  • System.out.println(inet3);??
  • ??
  • //?獲得對象中存儲(chǔ)的域名??
  • ??
  • String?host?=?inet3.getHostName();??
  • ??
  • System.out.println("域名:"?+?host);??
  • ??
  • //?獲得對象中存儲(chǔ)的IP??
  • ??
  • String?ip?=?inet3.getHostAddress();??
  • ??
  • System.out.println("IP:"?+?ip);??
  • ??
  • }?catch?(Exception?e)?{??
  • }??
  • }??
  • }??
  • ??</span>??
  • 注:InetAddress?類沒有明顯的構(gòu)造函數(shù)。為生成一個(gè)InetAddress對象,必須運(yùn)用一個(gè)可用的工廠方法。?

    –工廠方法(factory?method)僅是一個(gè)類中靜態(tài)方法返回一個(gè)該類實(shí)例的約定。對于InetAddress,三個(gè)方法?getLocalHost(?)、getByName(?)以及getAllByName(?)可以用來創(chuàng)建InetAddress的實(shí)例?

    ?如果這些方法不能解析主機(jī)名,它們引發(fā)一個(gè)UnknownHostException異常。?

    五:TCP編程

    在Java語言中,對于TCP方式的網(wǎng)絡(luò)編程提供了良好的支持,在實(shí)際實(shí)現(xiàn)時(shí),以java.net.Socket類代表客戶端連接,以java.net.ServerSocket類代表服務(wù)器端連接。在進(jìn)行網(wǎng)絡(luò)編程時(shí),底層網(wǎng)絡(luò)通訊的細(xì)節(jié)已經(jīng)實(shí)現(xiàn)了比較高的封裝,所以在程序員實(shí)際編程時(shí),只需要指定IP地址和端口號碼就可以建立連接了。

    在客戶端網(wǎng)絡(luò)編程中,首先需要建立連接,在Java?API中以java.net.Socket類的對象代表網(wǎng)絡(luò)連接

    客戶端

    1)?建立Socket連接?

    Socket?socket2?=?new?Socket(www.sohu.com,80);

    2)按照“請求-響應(yīng)”模型進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)交換

    在Java語言中,數(shù)據(jù)傳輸功能由Java?IO實(shí)現(xiàn),也就是說只需要從連接中獲得輸入流和輸出流即可,然后將需要發(fā)送的數(shù)據(jù)寫入連接對象的輸出流中,在發(fā)送完成以后從輸入流中讀取數(shù)據(jù)即可。示例代碼如下:

    ?OutputStream?os?=?socket1.getOutputStream();?//獲得輸出流

    ?InputStream?is?=?socket1.getInputStream();?????//獲得輸入流

    這里獲得的只是最基本的輸出流和輸入流對象,還可以根據(jù)前面學(xué)習(xí)到的IO知識(shí),使用流的嵌套將這些獲得到的基本流對象轉(zhuǎn)換成需要的裝飾流對象,從而方便數(shù)據(jù)的操作。

    3關(guān)閉網(wǎng)絡(luò)連接

    ?socket1.close();

    服務(wù)器端

    首先需要說明的是,客戶端的步驟和服務(wù)器端的編寫步驟不同,所以在學(xué)習(xí)服務(wù)器端編程時(shí)注意不要和客戶端混淆起來。

    1)監(jiān)聽端口

    ServerSocket?ss?=?new?ServerSocket(10000);

    2)獲得連接

    當(dāng)有客戶端連接到達(dá)時(shí),建立一個(gè)和客戶端連接對應(yīng)的Socket連?接對象,從而釋放客戶端連接對于服務(wù)器端端口的占用

    Socket?socket?=?ss.accept();

    該代碼實(shí)現(xiàn)的功能是獲得當(dāng)前連接到服務(wù)器端的客戶端連接。需要說明的是accept和前面IO部分介紹的read方法一樣,都是一個(gè)阻塞方法,也就是當(dāng)無連接時(shí),該方法將阻塞程序的執(zhí)行,直到連接到達(dá)時(shí)才執(zhí)行該行代碼。另外獲得的連接會(huì)在服務(wù)器端的該端口注冊,這樣以后就可以通過在服務(wù)器端的注冊信息直接通信,而注冊以后服務(wù)器端的端口就被釋放出來,又可以繼續(xù)接受其它的連接了。

    3)按照“請求-響應(yīng)”模型進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)交換

    這里獲得的Socket類型的連接就和客戶端的網(wǎng)絡(luò)連接一樣了,只是服務(wù)器端需要首先讀取發(fā)送過來的數(shù)據(jù),然后進(jìn)行邏輯處理以后再發(fā)送給客戶端,也就是交換數(shù)據(jù)的順序和客戶端交換數(shù)據(jù)的步驟剛好相反

    ?InputStream?is?=?ss.getInputStream();?????//獲得輸入流

    OutputStream?os?=?ss.getOutputStream();?//獲得輸出流

    4)關(guān)閉服務(wù)器端連接

    ss.close();

    以上就是基本的TCP類型的服務(wù)器和客戶端代碼實(shí)現(xiàn)的步驟,下面以一個(gè)簡單的echo(回聲)服務(wù)實(shí)現(xiàn)為例子,介紹綜合使用示例,實(shí)現(xiàn)的代碼如下:

    [java]?view plaincopy print?
  • public?class?Constants?{??
  • ??
  • ????public?static?void?main(String[]?args)?{??
  • ????????ServerSocket?serverSocket?=?null;??
  • ????????Socket?socket?=?null;??
  • ????????OutputStream?os?=?null;??
  • ????????InputStream?is?=?null;??
  • ????????//?監(jiān)聽端口號??
  • ????????int?port?=?10000;??
  • ????????try?{??
  • ????????????//?建立連接??
  • ????????serverSocket?=?new?ServerSocket(port);??
  • ????????????//?獲得連接??
  • ????????????socket?=?serverSocket.accept();??
  • ????????????//?接收客戶端發(fā)送內(nèi)容??
  • ????????????is?=?socket.getInputStream();??
  • ????????????byte[]?b?=?new?byte[1024];??
  • ????????????int?n?=?is.read(b);??
  • ????????????//?輸出??
  • ????????????System.out.println("客戶端發(fā)送內(nèi)容為:"?+?new?String(b,?0,?n));??
  • ????????????//?向客戶端發(fā)送反饋內(nèi)容??
  • ????????????os?=?socket.getOutputStream();??
  • ????????????os.write(b,?0,?n);??
  • ????????}?catch?(Exception?e)?{??
  • ????????e.printStackTrace();??
  • ????????}?finally?{??
  • ????????????try?{??
  • ????????????????//?關(guān)閉流和連接??
  • ????????????????os.close();??
  • ????????????????is.close();??
  • ????????????????socket.close();??
  • ????????????????serverSocket.close();??
  • ????????????}?catch?(Exception?e)?{??
  • ????????????}??
  • ????????}??
  • ????}??
  • }??
  • UDP編程

    ?????UDP(User?Datagram?Protocol),中文意思是用戶數(shù)據(jù)報(bào)協(xié)議使用該種方式無需建立專用的虛擬連接,由于無需建立專用的連接,所以對于服務(wù)器的壓力要比TCP小很多,所以也是一種常見的網(wǎng)絡(luò)編程方式。但是使用該種方式最大的不足是傳輸不可靠,當(dāng)然也不是說經(jīng)常丟失,就像大家發(fā)短信息一樣,理論上存在收不到的可能

    ?????在Java?API中,實(shí)現(xiàn)UDP方式的編程,包含客戶端網(wǎng)絡(luò)編程和服務(wù)器端網(wǎng)絡(luò)編程,主要由兩個(gè)類實(shí)現(xiàn),分別是:

    l?DatagramSocket

    DatagramSocket類實(shí)現(xiàn)“網(wǎng)絡(luò)連接”,包括客戶端網(wǎng)絡(luò)連接和服務(wù)器端網(wǎng)絡(luò)連接。雖然UDP方式的網(wǎng)絡(luò)通訊不需要建立專用的網(wǎng)絡(luò)連接,但是畢竟還是需要發(fā)送和接收數(shù)據(jù),DatagramSocket實(shí)現(xiàn)的就是發(fā)送數(shù)據(jù)時(shí)的發(fā)射器,以及接收數(shù)據(jù)時(shí)的監(jiān)聽器的角色。類比于TCP中的網(wǎng)絡(luò)連接,該類既可以用于實(shí)現(xiàn)客戶端連接,也可以用于實(shí)現(xiàn)服務(wù)器端連接。

    l?DatagramPacket

    DatagramPacket類實(shí)現(xiàn)對于網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)封裝,也就是說,該類的對象代表網(wǎng)絡(luò)中交換的數(shù)據(jù)。在UDP方式的網(wǎng)絡(luò)編程中,無論是需要發(fā)送的數(shù)據(jù)還是需要接收的數(shù)據(jù),都必須被處理成DatagramPacket類型的對象,該對象中包含發(fā)送到的地址、發(fā)送到的端口號以及發(fā)送的內(nèi)容等。其實(shí)DatagramPacket類的作用類似于現(xiàn)實(shí)中的信件,在信件中包含信件發(fā)送到的地址以及接收人,還有發(fā)送的內(nèi)容等,郵局只需要按照地址傳遞即可。在接收數(shù)據(jù)時(shí),接收到的數(shù)據(jù)也必須被處理成DatagramPacket類型的對象,在該對象中包含發(fā)送方的地址、端口號等信息,也包含數(shù)據(jù)的內(nèi)容。和TCP方式的網(wǎng)絡(luò)傳輸相比,IO編程在UDP方式的網(wǎng)絡(luò)編程中變得不是必須的內(nèi)容,結(jié)構(gòu)也要比TCP方式的網(wǎng)絡(luò)編程簡單一些。

    UDP客戶端編程涉及的步驟也是4個(gè)部分:建立連接、發(fā)送數(shù)據(jù)、接收數(shù)據(jù)和關(guān)閉連接。

    1)建立連接:

    DatagramSocket?ds?=?new?DatagramSocket();

    該客戶端連接使用系統(tǒng)隨機(jī)分配的一個(gè)本地計(jì)算機(jī)的未用端口號

    ?當(dāng)然,可以通過制定連接使用的端口號來創(chuàng)建客戶端連接。

    ??DatagramSocket?ds?=?new?DatagramSocket(5000);

    一般在建立客戶端連接時(shí)沒有必要指定端口號碼。

    2)發(fā)送數(shù)據(jù)

    在發(fā)送數(shù)據(jù)時(shí),需要將需要發(fā)送的數(shù)據(jù)內(nèi)容首先轉(zhuǎn)換為byte數(shù)組,然后將數(shù)據(jù)內(nèi)容、服務(wù)器IP和服務(wù)器端口號一起構(gòu)造成一個(gè)DatagramPacket類型的對象,這樣數(shù)據(jù)的準(zhǔn)備就完成了了,發(fā)送時(shí)調(diào)用網(wǎng)絡(luò)連接對象中的send方法發(fā)送該對象即可

    代碼示例:

    [java]?view plaincopy print?
  • <span?style="color:#333333;BACKGROUND-COLOR:?#666666">???String?s?=?"Hello";??
  • ????String?host?=?"127.0.0.1";??
  • ????int?port?=?10001;??
  • ???//將發(fā)送的內(nèi)容轉(zhuǎn)換為byte數(shù)組??
  • ????byte[]?b?=?s.getBytes();??
  • ????//將服務(wù)器IP轉(zhuǎn)換為InetAddress對象??
  • ????InetAddress?server?=?InetAddress.getByName(host);??
  • ????//構(gòu)造發(fā)送的數(shù)據(jù)包對象??
  • ????DatagramPacket?sendDp?=?new?DatagramPacket(b,b.length,server,port);??
  • ????//發(fā)送數(shù)據(jù)??
  • ????ds.send(sendDp);</span>??

  • ?

    ??????在該示例代碼中,不管發(fā)送的數(shù)據(jù)內(nèi)容是什么,都需要轉(zhuǎn)換為byte數(shù)組,然后將服務(wù)器端的IP地址構(gòu)造成InetAddress類型的對象,在準(zhǔn)備完成以后,將這些信息構(gòu)造成一個(gè)DatagramPacket類型的對象,在UDP編程中,發(fā)送的數(shù)據(jù)內(nèi)容、服務(wù)器端的IP和端口號,都包含在DatagramPacket對象中。在準(zhǔn)備完成以后,調(diào)用連接對象ds的send方法把DatagramPacket對象發(fā)送出去即可。

    3)UDP客戶端編程中接收數(shù)據(jù)

    ?????首先構(gòu)造一個(gè)數(shù)據(jù)緩沖數(shù)組,該數(shù)組用于存儲(chǔ)接收的服務(wù)器端反饋數(shù)據(jù),該數(shù)組的長度必須大于或等于服務(wù)器端反饋的實(shí)際有效數(shù)據(jù)的長度。然后以該緩沖數(shù)組為基礎(chǔ)構(gòu)造一個(gè)DatagramPacket數(shù)據(jù)包對象,最后調(diào)用連接對象的receive方法接收數(shù)據(jù)即可。接收到的服務(wù)器端反饋數(shù)據(jù)存儲(chǔ)在DatagramPacket類型的對象內(nèi)部

    示例代碼:

    [java]?view plaincopy print?
  • <span?style="BACKGROUND-COLOR:?#666666">??????//構(gòu)造緩沖數(shù)組??
  • ????byte[]?data?=?new?byte[1024];??
  • ????//構(gòu)造數(shù)據(jù)包對象??
  • ????DatagramPacket?receiveDp?=?new?DatagramPacket(data,data.length);??
  • ????//接收數(shù)據(jù)??
  • ????ds.receive(receiveDp);??
  • ????//輸出數(shù)據(jù)內(nèi)容??
  • ????byte[]?b?=?receiveDp.getData();?//獲得緩沖數(shù)組??
  • ????int?len?=?receiveDp.getLength();?//獲得有效數(shù)據(jù)長度??
  • ????String?s?=?new?String(b,0,len);??
  • ????System.out.println(s);</span>??

  • ?

    代碼講解?:??首先構(gòu)造緩沖數(shù)組data,這里設(shè)置的長度1024是預(yù)估的接收到的數(shù)據(jù)長度,要求該長度必須大于或等于接收到的數(shù)據(jù)長度,然后以該緩沖數(shù)組為基礎(chǔ),構(gòu)造數(shù)據(jù)包對象,使用連接對象ds的receive方法接收反饋數(shù)據(jù),由于在Java語言中,除String以外的其它對象都是按照地址傳遞,所以在receive方法內(nèi)部可以改變數(shù)據(jù)包對象receiveDp的內(nèi)容,這里的receiveDp的功能和返回值類似。數(shù)據(jù)接收到以后,只需要從數(shù)據(jù)包對象中讀取出來就可以了,使用DatagramPacket對象中的getData方法可以獲得數(shù)據(jù)包對象的緩沖區(qū)數(shù)組,但是緩沖區(qū)數(shù)組的長度一般大于有效數(shù)據(jù)的長度,換句話說,也就是緩沖區(qū)數(shù)組中只有一部分?jǐn)?shù)據(jù)是反饋數(shù)據(jù),所以需要使用DatagramPacket對象中的getLength方法獲得有效數(shù)據(jù)的長度,則有效數(shù)據(jù)就是緩沖數(shù)組中的前有效數(shù)據(jù)長度個(gè)內(nèi)容,這些才是真正的服務(wù)器端反饋的數(shù)據(jù)的內(nèi)容

    4)關(guān)閉連接

    ??ds.close();

    UDP方式服務(wù)器端網(wǎng)絡(luò)編程

    1)首先UDP方式服務(wù)器端網(wǎng)絡(luò)編程需要建立一個(gè)連接,該連接監(jiān)聽某個(gè)端口:

    ?DatagramSocket?ds?=?new?DatagramSocket(10010);

    由于服務(wù)器端的端口需要固定,所以一般在建立服務(wù)器端連接時(shí),都指定端口號

    2)接收客戶端發(fā)送過來的數(shù)據(jù)

    其接收的方法和客戶端接收的方法一直,其中receive方法的作用類似于TCP方式中accept方法的作用,該方法也是一個(gè)阻塞方法,其作用是接收數(shù)據(jù)。

    ds.receive()

    接收到客戶端發(fā)送過來的數(shù)據(jù)以后,服務(wù)器端對該數(shù)據(jù)進(jìn)行邏輯處理,然后將處理以后的結(jié)果再發(fā)送給客戶端,在這里發(fā)送時(shí)就比客戶端要麻煩一些,因?yàn)榉?wù)器端需要獲得客戶端的IP和客戶端使用的端口號,這個(gè)都可以從接收到的數(shù)據(jù)包中獲得。示例代碼如下:

    ?????//獲得客戶端的IP

    ?????InetAddress?clientIP?=?receiveDp.getAddress();

    ?????????//獲得客戶端的端口號

    ?????????Int?clientPort?=?receiveDp.getPort();

    3)關(guān)閉連接

    ds.close()

    ??????? 好了,占時(shí)就總結(jié)到這吧,總結(jié)的不是很全面,但很基礎(chǔ),應(yīng)該適合初學(xué)者學(xué)習(xí),由于本人也是初學(xué)者的小菜鳥,所有很多東西可能都涉及不到,希望大家見諒!

    ?

    ?本文來自:曹勝歡博客專欄。轉(zhuǎn)載請注明出處:http://blog.csdn.net/csh624366188

    總結(jié)

    以上是生活随笔為你收集整理的Java程序员从笨鸟到菜鸟之(十三)java网络通信编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。