Java高級篇(二)——網絡通信

  網絡編程是每個開發人員工具箱中的核心部分,我們在學習了諸多Java的知識后,也將步入幾個大的方向,Java網絡編程就是其中之一。

  如今強調網絡的程序不比涉及網絡的更多。除了經典的應用程序,如電子郵件、Web瀏覽器和遠程登陸外,大多數主要的應用程序都有某種程度的內質網絡功能。比如我們最常使用的IDE(Eclipse/IDEA)與源代碼存儲庫(GitHub等等)進行通信;再比如Word,可以從URL打開文件;又或者是我們玩的眾多聯機游戲,玩家實時相互對戰等等。Java是第一個從一開始就為網絡應用而設計的編程語言,最早的兩個實用Java應用的程序之一就是Web瀏覽器,隨著Internet的不斷發展,Java成為了唯一適合構建下一代網絡應用程序的語言。(節選自Java NetWork Programming——Elliotte Rusty Harold著

一、Client/Server

  為了實現兩臺計算機的通信,必須要用一個網絡線路連接兩臺計算機。服務器(Server)是指提供信息的計算機或程序,客戶機(Client)是指請求信息的計算機或程序,而網絡用于連接服務器與客戶機,實現兩者相互通信。

  下面我們看一個簡單的通信例子。

  如下的Server程序是一個服務器端應用程序,使用 Socket 來監聽一個指定的端口。

 1 import java.io.IOException;
 2 import java.io.InputStreamReader;
 3 import java.io.Reader;
 4 import java.net.ServerSocket;
 5 import java.net.Socket;
 6 
 7 public class Server {
 8 
 9     public static void main(String[] args) throws IOException {
10         int port = 9999;
11         
12         System.out.println("-----------服務器啟動-----------");
13         
14         ServerSocket server = new ServerSocket(port);
15         Socket socket = server.accept();
16         Reader reader = new InputStreamReader(socket.getInputStream());
17         char chars[] = new char[1024];
18         int len;
19         StringBuilder builder = new StringBuilder();
20         while ((len=reader.read(chars)) != -1) {
21            builder.append(new String(chars, 0, len));
22         }
23         System.out.println("收到來自客戶端的信息: " + builder);
24         reader.close();
25         socket.close();
26         server.close();
27     }
28 
29 }

?  如下的Client是一個客戶端程序,該程序通過 socket 連接到服務器并發送一個請求,然后等待一個響應。

 1 import java.io.IOException;
 2 import java.io.OutputStreamWriter;
 3 import java.io.Writer;
 4 import java.net.Socket;
 5 import java.util.Scanner;
 6 
 7 public class Client {
 8 
 9     public static void main(String[] args) throws IOException {
10         String host = "127.0.0.1";
11         int port = 9999;
12         
13         System.out.println("-----------客戶端啟動-----------");
14         
15         Socket client = new Socket(host, port);
16         Writer writer = new OutputStreamWriter(client.getOutputStream());
17         Scanner in = new Scanner(System.in);
18         writer.write(in.nextLine());
19         writer.flush();
20         writer.close();
21         client.close();
22         in.close();
23     }
24     
25 }

  先啟動服務器,運行結果如下:

  

  再運行客戶端,并輸入要發送的信息,如下:

  

  此時Server就接收到了Client發送的消息,如下:

  

  這就是一個簡單的套接字通信了,具體分析見下方TCP。

二、TCP

  TCP網絡程序設計是指利用Socket類編寫通信程序,具體實例參照上例。

  套接字使用TCP提供了兩臺計算機之間的通信機制。 客戶端程序創建一個套接字,并嘗試連接服務器的套接字。當連接建立時,服務器會創建一個 Socket 對象。客戶端和服務器現在可以通過對 Socket 對象的寫入和讀取來進行通信。java.net.Socket 類代表一個套接字,并且 java.net.ServerSocket 類為服務器程序提供了一種來監聽客戶端,并與他們建立連接的機制。

  兩臺計算機間使用套接字建立TCP連接步驟如下:

  • 服務器實例化一個 ServerSocket 對象,表示通過服務器上的端口通信。

  • 服務器調用 ServerSocket 類的 accept() 方法,該方法將一直等待,直到客戶端連接到服務器上給定的端口。

  • 服務器正在等待時,一個客戶端實例化一個 Socket 對象,指定服務器名稱和端口號來請求連接。

  • Socket 類的構造函數試圖將客戶端連接到指定的服務器和端口號。如果通信被建立,則在客戶端創建一個 Socket 對象能夠與服務器進行通信。

  • 在服務器端,accept() 方法返回服務器上一個新的 socket 引用,該 socket 連接到客戶端的 socket。

  連接建立后,通過使用 I/O 流在進行通信,每一個socket都有一個輸出流和一個輸入流,客戶端的輸出流連接到服務器端的輸入流,而客戶端的輸入流連接到服務器端的輸出流。

  1. InetAddress

  java.net包中的InetAddress類是與IP地址相關的類,利用該類可以獲取IP地址、主機地址等信息。

InetAddress ip = InetAddress.getLocalHost();
String localName = ip.getHostName();    //獲取本地主機名
String localIp = ip.getHostAddress();    //獲取本地主機的ip地址

  2. ServerSocket?

  java.net包中的ServetSocket類用于表示服務器套接字,其主要功能是等待來自網絡上的“請求”,它可以通過指定的端口來等待連接的套接字(如上方實例中的9999)。

  而服務器套接字一次可以與一個套接字連接,如果多臺客戶機同時提出連接請求,服務器套接字會將請求連接的客戶機存入隊列中,然后從中取出一個套接字,與服務器新建的套接字連接起來。若請求連接數大于最大容納數,則多出的連接請求被拒絕。

  ServerSocket的具體方法可參照API,這里只對accept()方法進行一個說明。調用accept()方法將返回一個與客戶端Socket對象相連的Socket對象,服務器端的Socket對象使用getOutputStream()方法獲得的輸出流對象,將指向客戶端Socket對象使用getInputStream()方法獲得的輸入流對象,反之亦然。

  需要注意的是,accept()方法會阻塞線程的繼續執行,直到接受客戶的呼叫,如果沒有客戶呼叫服務器,那么下面的代碼將不會執行。

三、UDP

  用戶數據包協議(UDP)是網絡信息傳輸的另一種形式,基于UDP的通信與基于TCP的通信不同,UDP的信息傳遞更快,但不提供可靠的保證。

  1. DatagramPacket

  java.net包中的DatagramPacket類用來表示數據包,構造方法如下:

DatagramPacket(byte[] buf, int length)
DatagramPacket(byte[] buf, int length, InetAddress address, int port)

  上述構造方法中,第一種指定了數據包的內存空間和大小,第二種不僅指定了數據包的內存空間和大小,并且指定了數據包的目標地址和端口。

  2. DatagramSocket

  java.net包中的DatagramSocket類用于表示發送和接受數據包的套接字,構造方法如下:

DatagramSocket()
DatagramSocket(int port)
DatagramSocket(int port, InetAddress addr)

  上述構造方法中,第一種創建數據包套接字并將其綁定到本地主機上任何可用的端口,第二種創建數據包套接字并將其綁定到本地主機上的指定端口,創建數據包套接字并將其綁定到指定的本機地址

?四、實例測試

  下面寫一個完整的實例,題目如下:

  • 建立服務端程序,服務器端程序接收來自客戶端的請求;
  • 從網上下載程序,英語900句,每句占一行;
  • 服務端讀取該文件,保存到集合或者列表中;
  • 建立客戶端程序,使用”sentence: <編號#>,<編號#>”的格式發生數據。例如:發送”sentense:1,2,3” , 服務端把相應編號的句子發送給客戶端,并加以呈現;
  • 客戶端需要把服務端發送的句子保存起來,如果已經保存有相應的句子,將不再保存;
  • 客戶端需要把從服務端獲取的數據存儲到文件中。

?  1. 程序結構

  

  2. Server.java

  該類為客戶端類。

 1 import java.io.*;
 2 import java.net.ServerSocket;
 3 import java.net.Socket;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 
 7 /**
 8  * 
 9  * @author adamjwh
10  *
11  */
12 public class Server {
13     
14     public static List<String> sentence;
15     private static String filename = "src/com/adamjwh/jnp/ex6_2/English900.txt";
16     
17     public static void main(String[] args) throws IOException {
18         sentence=new ArrayList<>();
19         System.out.println("-----------服務器啟動-----------");
20         
21         FileReader fileReader = new FileReader(filename);
22         BufferedReader br = new BufferedReader(fileReader);
23         
24         String inputLine = null;
25         while ((inputLine = br.readLine()) != null) {
26             sentence.add(inputLine);
27         }
28 
29         ServerSocket ss = new ServerSocket(9999);
30         while(true){
31             Socket sk =ss.accept();
32             ServerThread st = new ServerThread(sk);
33             st.start();
34         }
35         
36     }
37 }

  2. Client.java

  該類為服務器類。

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;/*** * @author adamjwh**/
public class Client {private static String filename = "src/com/adamjwh/jnp/ex6_2/result.txt";public static void main(String[] args) {try {Socket sk = new Socket("127.0.0.1", 9999);System.out.println("-----------客戶端啟動-----------");PrintStream ps = new PrintStream(sk.getOutputStream());System.out.print("發送:");Scanner sn = new Scanner(System.in);String str = sn.nextLine();ps.println(str);InputStream is = sk.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);//寫文件FileWriter fw = new FileWriter(filename, true);//讀文件String result = new ReadFile().readFile(filename);String s;while ((s = br.readLine()) != null) {System.out.println("服務器推送:" + s);if(!result.contains(s)) {fw.write(s + "\n");}}sk.shutdownInput();ps.close();sk.close();fw.close();} catch (Exception e) {e.printStackTrace();}}
}

  3. ServerThread

  通過線程實現信息交互。

 1 import java.io.*;
 2 import java.net.Socket;
 3 
 4 /**
 5  * 
 6  * @author adamjwh
 7  *
 8  */
 9 public class ServerThread extends Thread{
10     Socket sk;
11     public ServerThread(Socket sk){
12         this.sk= sk;
13     }
14     public void run() {
15         BufferedReader br=null;
16         try{
17             br  = new BufferedReader(new InputStreamReader(sk.getInputStream()));
18             String line = br.readLine();
19             System.out.println("客戶端:"+line);
20             String[] split = line.split(":");
21             String[] split1 = split[split.length - 1].split(",");
22             sk.shutdownInput();
23 
24             OutputStream os = sk.getOutputStream();
25 
26             PrintStream bw = new PrintStream(os);
27 
28             //給客戶端返回信息
29             for(int i=0;i<split1.length;i++) {
30                 bw.print(Server.sentence.get(Integer.parseInt(split1[i])%Server.sentence.size())+"\n");
31             }
32             bw.flush();
33             br.close();
34             sk.close();
35         }
36         catch(IOException e){
37             e.printStackTrace();
38         }
39     }
40 }

?  4. 運行結果

  先運行服務器

  

  再運行客戶端,并輸入信息

  

  服務器接收到客戶端發來的請求

  

?  服務器將請求結果推送給客戶端,這里客戶端就獲取到了它請求的第174句、第258句及第5句,并輸出到文件中

  

  這里的測試文件我測試到了162(也就是該文件的第15行),可以看到在文件中追加了兩行新的句子(174和258),而第5句因為在之前已經出現過了(該文件的第1行),所以沒有追加第5句,完成上述題目。

  

轉載于:https://www.cnblogs.com/adamjwh/p/8856516.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/278131.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/278131.shtml
英文地址,請注明出處:http://en.pswp.cn/news/278131.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Navigator 對象,能夠清楚地知道瀏覽器的相關信息

Navigator 對象屬性 appCodeName屬性 功能&#xff1a;返回瀏覽器的代碼名。該屬性是一個只讀的字符串。 語法&#xff1a;navigator.appCodeName 總結&#xff1a;在所有以Netscape代碼為基礎的瀏覽器中&#xff0c;它的值是"Mozilla"。為了兼容起見&#xff0c;在M…

Jerry和您聊聊Chrome開發者工具

2019獨角獸企業重金招聘Python工程師標準>>> Chrome開發者工具是Jerry日常工作使用的三大調試器之一。雖然工具名稱前面帶了個"開發者", 但是它對非開發人員仍然有用。不信&#xff1f; 用Chrome打開我們常用的網站&#xff0c;按F12&#xff0c;在Consol…

BZOJ4314 倍數?倍數!

好神仙啊.... 題意 在$ [0,n) $中選$ k$個不同的數使和為$ n$的倍數 求方案數 $ n \leq 10^9, \ k \leq 10^3$ 題解 k可以放大到1e6的 先不考慮$ k$的限制 對答案構建多項式$ f(x)\prod\limits_{i0}^{n-1}(x^i1)$ 答案就是這個多項式所有次數為$ n$的倍數的項的系數和 考慮單位…

win2008R2管理員密碼修改文檔

場景&#xff1a;忘記了win2008R2服務器的管理員密碼。解決辦法&#xff1a;1、 制作一個U盤啟動盤&#xff1a;2、 系統通過U盤啟動進入WINpe系統3、 在知道Win2008安裝位置的情況下&#xff1b;查找C:\windows\system32\osk.exe 將osk.exe文件修改為&#xff1a;osk.exe.bat&…

Python檔案袋( 面向對象 )

類即是一個模型&#xff0c;根據模型建立起不同的對象&#xff0c;對象間擁有共同的一些屬性 簡單的類&#xff1a; 1 class P:2 #類變量&#xff0c;所有實例共享變量,推薦使用方法是&#xff1a;類名.類變量名3 pvarx"ppvar1"4 5 #構造函數6 def _…

javascript中的后退和刷新

轉自&#xff1a;https://www.cnblogs.com/tylerdonet/p/3911303.html <input typebutton value刷新 οnclick"window.location.reload()"><input typebutton value前進 οnclick"window.history.go(1)"><input typebutton value后退 οncl…

第四周

7-2 選擇法排序 &#xff08;20 分) 本題要求將給定的n個整數從大到小排序后輸出。 輸入格式&#xff1a; 輸入第一行給出一個不超過10的正整數n。第二行給出n個整數&#xff0c;其間以空格分隔。 輸出格式&#xff1a; 在一行中輸出從大到小有序的數列&#xff0c;相鄰數字間有…

checkPathValidity 檢查所有agent的corridor的m_path是否有效

在checkPathValidity&#xff08;檢查所有agent的corridor的m_path是否有效&#xff09; 如果是無效的要進行重新設置并且設置replan 首先獲得第一個polygon&#xff0c;m_path[0] 這里&#xff0c;因為addagent的時候&#xff0c;ag->corridor.reset(ref, nearest); m_path…

來談談JAVA面向對象 - 魯班即將五殺,大喬送他回家??

開發IDE為Eclipse或者MyEclipse。 首先&#xff0c;如果我們使用面向過程的思維來解決這個問題&#xff0c;就是第一步做什么&#xff0c;第二步做什么&#xff1f; 魯班即將五殺&#xff0c;大喬送他回家 這個現象可以簡單地拆分為兩步&#xff0c;代碼大概是這個樣子的: publ…

Vue 教程第一篇——基礎概念

認識 Vue 關于 Vue 的描述有不少&#xff0c;不外乎都會拿來與 Angular 和 React 對比&#xff0c;同樣頭頂 MVVM 雙向數據驅動設計模式光環的 Angular 自然被對比的最多&#xff0c;但到目前為止&#xff0c;Angular 在熱度上已明顯不及 Vue&#xff0c;性能已成為最大的詬病。…

Microsoft Teams的Outgoing Webhook開發入門

Microsoft Teams的應用程序有幾種形式&#xff1a; TabsBotsConnectorsMessaging extensionsActivity feed integrationsOutgoing web hooks 這篇我們主要介紹如何使用 ASP.NET Core來開發最簡單的Outgoing web hook。 什么是outgoing webhook Outgoing webhooks allow you t…

0418 jQuery筆記(添加事件、each、prop、$(this))

1.添加點擊事件、each、prop、$(this) 1 //全選框的被動操作2 //定義一個標志保存最終狀態3 var flag false;4 //為每一個選擇框添加點擊事件&#xff0c;數組.click()5 $(.chex).click(function(){6 //遍歷數組&#xff0c;數組.each()7 …

[WC2008]游覽計劃(斯坦納樹)

[Luogu4294] 題解 : 斯坦納樹 \(dp[i][j]\) 表示以\(i\)號節點為根&#xff0c;當前狀態為\(j\)&#xff08;與\(i\)連通的點為\(1\)&#xff09; 當根\(i\)不改變時狀態轉移方程是&#xff1a; \(dp[i][j] \min_{s \in j}\{dp[i][s] dp[i][\complement_js] - val[i]\}\) 當根…

使用dotnet template快速開發Microsoft Teams Outgoing Web Hook

在上一篇文章中&#xff0c;我們一步步從無到有在Microsoft Teams中開發了一個簡單的Outgoing Webhook&#xff0c;并和我們本地的Web API應用程序產生交互&#xff0c;總結起來的步驟大概如下&#xff1a; 導航到“團隊” Tab頁&#xff0c; 選中需要建立的Channel, 選中“應…

[Swift]LeetCode1013. 將數組分成和相等的三個部分 | Partition Array Into Three Parts With Equal Sum...

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★?微信公眾號&#xff1a;山青詠芝&#xff08;shanqingyongzhi&#xff09;?博客園地址&#xff1a;山青詠芝&#xff08;https://www.cnblogs.com/strengthen/&#xff09;?GitHub地址&a…

京津冀產業協同升級 智慧城市等高端產業需求遇熱

云計算、智慧交通、城市環保科技等高端智慧城市產業項目正成為京津冀產業協同的新關注點。 21日&#xff0c;在由北京市經信委、天津市工信委、河北省工信廳聯合組織的京津冀產業協同發展招商推介專項行動上&#xff0c;超過200家與會企業共完成產業對接項目額達311.7億元。與以…

Microsoft Teams:刪除成員賬戶其歷史聊天會發生什么?

介紹&#xff1a; 此博客文章的目的是演示從Office 365刪除用戶的賬號后&#xff0c;此用戶在Microsoft Teams群聊和私聊中的歷史聊天記錄會發生什么改變。 以下是Microsoft Teams聊天對話&#xff0c;其中Adele和其他團隊成員正在參與對話&#xff1a; 此外, Adele和Mega還在…

PostgreSQL Huge Page 使用建議 - 大內存主機、實例注意

標簽 PostgreSQL , Linux , huge page , shared buffer , page table , 虛擬地址 , 物理地址 , 內存地址轉換表 背景 當內存很大時&#xff0c;除了刷臟頁的調度可能需要優化&#xff0c;還有一方面是虛擬內存與物理內存映射表相關的部分需要優化。 1 臟頁調度優化 1、主要包括…

Microsoft Teams:團隊Owner離開公司后,我們該怎么做?

您是否曾在這么一個團隊里&#xff0c;該團隊唯一有Owner權限的人離開了公司&#xff1f;不幸的是,如果這個人不再在公司里&#xff0c;您可能覺得沒有辦法讓其他團隊成員再成為team的owner。我有一個簡單易用的解決方案&#xff0c;但您需要成為Office 365租戶的Admin或聯系你…

python網絡編程-socket編程

一、服務端和客戶端 BS架構 &#xff08;騰訊通軟件&#xff1a;serverclient&#xff09; CS架構 &#xff08;web網站&#xff09; C/S架構與socket的關系&#xff1a; 我們學習socket就是為了完成C/S架構的開發 二、OSI七層模型 互聯網協議按照功能不同分為osi七層或tcp/ip五…