第二十一章博客

計算機應用實現了多臺計算機間的互聯,使得它們彼此之間能夠進行數據交流。網絡應用程序就是在已連接的不同計算機上運行的程序,這些程序借助于網絡協議,相互之間可以交換數據。編寫網絡應用程序前,首先必須明確所要使用的網絡協議。TCP/IP協議是網絡應用程序的首選

21.1 網絡程序設計基礎
網絡程序設計編寫的是與其他計算機進行通信的程序。Java已經將網絡程序所需要的元素封裝成不同的類,用戶只要創建這些類的對象,使用相應的方法,即使不具備有關的網絡知識,也可以編寫出高質量的網絡通信程序。

21.1.1 局域網與互聯網
為了實現兩臺計算機的通信,必須用一個網絡線路連接兩臺計算機

服務器是指提供信息的計算機或程序,客戶機是指請求信息的計算機或程序。網絡用于連接服務器與客戶機,實現兩者間的相互通信。但是,有時在某個網絡中很難將服務器與客戶機區分開。我們通常所說的局域網(Local Area Network,LAN),就是一群通過一定形式連接起來的計算機,它可以由兩臺計算機組成,也可以由同一區域內的上千臺計算機組成。將LAN延伸到更大的范圍,這樣的網絡稱為廣域網(Wide Area Network,WAN)。我們熟悉的互聯網(Internet),就是由無數的LAN和WAN組成的。

21.1.2 網絡協議
網絡協議規定了計算機之間連接的物理、機械(網線與網卡的連接規定)、電氣(有效的電平范圍)等特征,計算機之間的相互尋址規則,數據發送沖突的解決方式,長數據如何分段傳送與接收等內容。就像不同的國家有不同的法律一樣,目前網絡協議也有多種。下面簡單地介紹幾個常用的網絡協議。

1.IP協議
IP是Internet Protocol的簡稱,是一種網絡協議。Internet網絡采用的協議是TCP/IP協議,其全稱是Transmission Control Protocol/Internet Protocol。Internet依靠TCP/IP協議,在全球范圍內實現了不同硬件結構、不同操作系統、不同網絡系統間的互聯。在Internet網絡上存在著數以億計的主機,每臺主機都用網絡為其分配的Internet地址代表自己,這個地址就是IP地址。到目前為止,IP地址用4個字節,也就是32位的二進制數來表示,稱為IPv4。為了便于使用,通常取用每個字節的十進制數,并且每個字節之間用圓點隔開來表示IP地址,如192.168.1.1。現在人們正在試驗使用16個字節來表示IP地址,這就是IPv6,但IPv6還沒有投入使用。

TCP/IP模式是一種層次結構,共分為4層,分別為應用層、傳輸層、互聯網層和網絡層。各層實現特定的功能,提供特定的服務和訪問接口,并具有相對的獨立性。

2.TCP與UDP協議
在TCP/IP協議棧中,有兩個高級協議是網絡應用程序編寫者應該了解的,即傳輸控制協議(Transmission Control Protocol,TCP)與用戶數據報協議(User Datagram Protocol,UDP)。

TCP協議是一種以固接連線為基礎的協議,它提供兩臺計算機間可靠的數據傳送。TCP可以保證數據從一端送至連接的另一端時,能夠確實送達,而且抵達的數據的排列順序和送出時的順序相同。因此,TCP協議適合可靠性要求比較高的場合。就像撥打電話,必須先撥號給對方,等兩端確定連接后,相互才能聽到對方說話,也知道對方回應的是什么。

HTTP、FTP和Telnet等都需要使用可靠的通信頻道。例如,HTTP從某個URL讀取數據時,如果收到的數據順序與發送時不相同,可能就會出現一個混亂的HTML文件或是一些無效的信息。

UDP是無連接通信協議,不保證數據的可靠傳輸,但能夠向若干個目標發送數據,或接收來自若干個源的數據。UDP以獨立發送數據包的方式進行。這種方式就像郵遞員送信給收信人,可以寄出很多信給同一個人,且每一封信都是相對獨立的,各封信送達的順序并不重要,收信人接收信件的順序也不能保證與寄出信件的順序相同。

UDP協議適合于一些對數據準確性要求不高,但對傳輸速度和時效性要求非常高的網站,如網絡聊天室、在線影片等。這是由于TCP協議在認證上存在額外耗費,可能使傳輸速度減慢,而UDP協議即使有一小部分數據包遺失或傳送順序有所不同,也不會嚴重危害該項通信。

注意

一些防火墻和路由器會設置成不允許UDP數據包傳輸,因此若遇到UDP連接方面的問題,應先確定所在網絡是否允許UDP協議。

21.1.3 端口與套接字
一般而言,一臺計算機只有單一的連到網絡的物理連接(Physical Connection),所有的數據都通過此連接對內、對外送達特定的計算機,這就是端口。網絡程序設計中的端口(port)并非真實的物理存在,而是一個假想的連接裝置。端口被規定為一個在0~65535的整數。HTTP服務一般使用80端口,FTP服務使用21端口。假如一臺計算機提供了HTTP、FTP等多種服務,那么客戶機會通過不同的端口來確定連接到服務器的哪項服務上,如圖21.3所示。

通常,0~1023的端口數用于一些知名的網絡服務和應用,用戶的普通網絡應用程序應該使用1024以上的端口數,以避免端口號與另一個應用或系統服務所用端口沖突。

網絡程序中的套接字(Socket)用于將應用程序與端口連接起來。套接字是一個假想的連接裝置,就像插座一樣可連接電器與電線,如圖21.4所示。Java將套接字抽象化為類,程序設計者只需創建Socket類對象,即可使用套接字。

21.2 TCP程序
TCP網絡程序設計是指利用Socket類編寫通信程序。利用TCP協議進行通信的兩個應用程序是有主次之分的,一個稱為服務器程序,另一個稱為客戶機程序,兩者的功能和編寫方法大不一樣。

①——服務器程序創建一個ServerSocket(服務器端套接字)對象,調用accept()方法等待客戶機來連接。

②——客戶端程序創建一個Socket對象,請求與服務器建立連接。

③——服務器接收客戶機的連接請求,同時創建一個新的Socket對象與客戶建立連接。隨后服務器繼續等待新的請求。

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

?使用InetAddress類的getHostName()和getHostAddress()方法獲得本地主機的本機名、本機IP地址。

注意

InetAddress類的方法會拋出UnknownHostException異常,所以必須進行異常處理。這個異常在主機不存在或網絡連接錯誤時發生。

21.2.2 ServerSocket類
java.net包中的ServerSocket類用于表示服務器套接字,其主要功能是等待來自網絡上的“請求”,它可通過指定的端口來等待連接的套接字。服務器套接字一次可以與一個套接字連接。如果多臺客戶機同時提出連接請求,服務器套接字會將請求連接的客戶機存入列隊中,然后從中取出一個套接字,與服務器新建的套接字連接起來。若請求連接數大于最大容納數,則多出的連接請求被拒絕。隊列的默認大小是50。

ServerSocket類的構造方法通常會拋出IOException異常,具體有以下幾種形式:

?ServerSocket():創建非綁定服務器套接字。
ServerSocket(int port):創建綁定到特定端口的服務器套接字。
ServerSocket(int port, int backlog):利用指定的backlog創建服務器套接字,并將其綁定到指定的本地端口號上。
ServerSocket(int port, int backlog, InetAddress bindAddress):使用指定的端口、偵聽backlog和要綁定到的本地IP地址創建服務器。這種情況適用于計算機上有多塊網卡和多個IP地址的情況,用戶可以明確規定ServerSocket在哪塊網卡或哪個IP地址上等待客戶的連接請求。


調用ServerSocket類的accept()方法,會返回一個和客戶端Socket對象相連接的Socket對象。服務器端的Socket對象使用getOutputStream()方法獲得的輸出流,將指向客戶端Socket對象使用getInputStream()方法獲得的那個輸入流;同樣,服務器端的Socket對象使用getInputStream()方法獲得的輸入流,將指向客戶端Socket對象使用getOutputStream()方法獲得的那個輸出流。也就是說,當服務器向輸出流寫入信息時,客戶端通過相應的輸入流就能讀取,反之亦然。

注意

accept()方法會阻塞線程的繼續執行,直到接收到客戶的呼叫。如果沒有客戶呼叫服務器,那么System.out.println("連接中")語句將不會執行。語句如果沒有客戶請求,accept()方法沒有發生阻塞,肯定是程序出現了問題。通常是使用了一個被其他程序占用的端口號,ServerSocket綁定沒有成功。

yu = server.accept();

System.out.println("連接中");

21.2.3 TCP網絡程序設計
明白了TCP程序工作的過程,就可以編寫TCP服務器程序了。在網絡編程中,如果只要求客戶機向服務器發送消息,不要求服務器向客戶機發送消息,稱為單向通信。客戶機套接字

和服務器套接字連接成功后,客戶機通過輸出流發送數據,服務器則通過輸入流接收數據。下面是簡單的單向通信的實例。

【例21.2】創建TCP/IP協議服務器

運行服務器端程序,將輸出提示信息,等待客戶呼叫。下面再來看一下客戶端程序。

編寫客戶端程序,將用戶在文本框中輸入的信息發送至服務器端,并將文本框中輸入的信息顯示在客戶端的文本域中。

說明

當一臺機器上安裝了多個網絡應用程序時,很可能指定的端口號已被占用。還可能遇到以前運行良好的網絡程序突然運行不了的情況,這種情況很可能也是由于端口被別的程序占用了。此時可以運行netstat-help來獲得幫助,使用netstat-an命令來查看該程序所使用的端口

21.3 UDP程序
用戶數據報協議(UDP)是網絡信息傳輸的另一種形式。基于UDP的通信和基于TCP的通信不同,基于UDP的信息傳遞更快,但不提供可靠性保證。使用UDP傳遞數據時,用戶無法知道數據能否正確地到達主機,也不能確定到達目的地的順序是否和發送的順序相同。雖然UDP是一種不可靠的協議,但如果需要較快地傳輸信息,并能容忍小的錯誤,可以考慮使用UDP。

基于UDP通信的基本模式如下:

將數據打包(稱為數據包),然后將數據包發往目的地。

接收別人發來的數據包,然后查看數據包。

發送數據包的步驟如下:

(1)使用DatagramSocket()創建一個數據包套接字。

(2)使用DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)創建要發送的數據包。

(3)使用DatagramSocket類的send()方法發送數據包。

接收數據包的步驟如下:

(1)使用DatagramSocket(int port)創建數據包套接字,綁定到指定的端口。

(2)使用DatagramPacket(byte[] buf, int length)創建字節數組來接收數據包。

(3)使用DatagramPacket類的receive()方法接收UDP包。

注意

DatagramSocket類的receive()方法接收數據時,如果還沒有可以接收的數據,在正常情況下receive()方法將阻塞,一直等到網絡上有數據傳來,receive()方法接收該數據并返回。如果網絡上沒有數據發送過來,receive()方法也沒有阻塞,肯定是程序有問題,大多數情況下是因為使用了一個被其他程序占用的端口號。

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

DatagramPacket(byte[] buf, int length)。
DatagramPacket(byte[] buf, int length, InetAddress address, int port)。
第一種構造方法在創建DatagramPacket對象時,指定了數據包的內存空間和大小。第二種構造方法不僅指定了數據包的內存空間和大小,還指定了數據包的目標地址和端口。在發

送數據時,必須指定接收方的Socket地址和端口號,因此使用第二種構造方法可創建發送數據的DatagramPacket對象。

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

DatagramSocket()。
DatagramSocket(int port)。
DatagramSocket(int port, InetAddress addr)。
第一種構造方法創建DatagramSocket對象,構造數據報套接字,并將其綁定到本地主機任何可用的端口上。第二種構造方法創建DatagramSocket對象,創建數據報套接字,并將其綁定到本地主機的指定端口上。第三種構造方法創建DatagramSocket對象,創建數據報套接字,并將其綁定到指定的端口和指定的本地地址上。第三種構造函數適用于有多塊網卡和多個IP地址的情況。

如果接收數據時必須指定一個端口號,不允許系統隨機產生,此時可以使用第二種構造方法。比如有個朋友要你給他寫信,那他的地址就必須確定,不確定是不行的。在發送數據時通常使用第一種構造方法,不指定端口號,而是系統為我們分配一個端口號,就像寄信不需要到指定的郵局去寄一樣。

21.3.3 UDP網絡程序設計
根據前面所講的網絡編程的基本知識以及UDP網絡編程的特點,下面創建一個廣播數據報程序。廣播數據報是一項較新的技術,其原理類似于電臺廣播。廣播電臺需要在指定的波段和頻率上廣播信息,收聽者也要將收音機調到指定的波段、頻率,才可以收聽廣播內容。

【例21.3】創建UDP協議廣播電臺程序
接收廣播程序。單擊“開始接收”按鈕,系統開始接收主機播出的信息;單擊“停止接收”按鈕,系統停止接收廣播主機播出的信息。代碼如下:

說明

發出廣播和接收廣播的主機地址必須位于同一個組內,地址范圍為224.0.0.0~224.255.255.255,該地址并不代表某個特定主機的位置。加入同一個組的主機可以在某個端口上廣播信息,也可以在某個端口上接收信息。
?

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

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

相關文章

Node.js中處理特殊字符的文件名,安全穩妥的方案

在Node.js中,通過path模塊提供的basename方法,我們可以輕松地從文件路徑中提取文件名。然而,這個方法在處理特殊字符時存在一些問題,因為它會對這些字符進行轉義,導致在不同操作系統上的兼容性問題。在這篇文章中&…

C++ boost planner_cond_.wait(lock) 報錯1225

1.如下程序段 boost unique_lock doesn’t own the mutex: Operation not permitted 問題: 其中makePlan是一個線程。這里的unlock導致錯誤這個報錯 boost unique_lock doesn’t own the mutex: Operation not permitted bool navigation::makePlan(){ //cv::named…

MySQL中如何快速定位占用CPU過高的SQL

作為DBA工作中都會遇到過數據庫服務器CPU飆升的場景,我們該如何快速定位問題?又該如何快速找到具體是哪個SQL引發的CPU異常呢?下面我們說兩個方法。聊聊MySQL中如何快速定位占用CPU過高的SQL。 技術人人都可以磨煉,但處理問題的思…

華為OD機試 - 多段線數據壓縮(Java JS Python C)

在線OJ刷題 題目詳情 - 多段線數據壓縮 - Hydro 題目描述 下圖中,每個方塊代表一個像素,每個像素用其行號和列號表示。 為簡化處理,多線段的走向只能是水平、豎直、斜向45度。 上圖中的多線段可以用下面的坐標串表示:(2,8),(3,7),(3,6),(3,5),(4,4),(5,3),(6,2),(7,3),(…

042、序列模型

之——從時序中獲取信息 目錄 之——從時序中獲取信息 雜談 正文 1.建模 2.方案A-馬爾科夫假設 3.方案B-潛變量模型 4.簡單實現 雜談 很多連續的數據都是有前后的時間相關性的,并不是每一個單獨的數據是隨機出現的。在時序中會蘊含一些空間結構的變化信息、…

【數據科學】一文徹底理清數據、數據類型、數據結構的概念

一、什么是數據? 入門數據學科,首先第一步要認識數據什么,可能大多數人都無法對數據做一個準確的定義,在我們印象中,提到數據首先頭腦浮現的是數據表格,是一堆堆數字,那么數據就是數字嗎&#x…

SpringBoot 2.0 中默認 HikariCP 數據庫連接池原理解析

作為后臺服務開發,在日常工作中我們天天都在跟數據庫打交道,一直在進行各種CRUD操作,都會使用到數據庫連接池。按照發展歷程,業界知名的數據庫連接池有以下幾種:c3p0、DBCP、Tomcat JDBC Connection Pool、Druid 等&am…

阿里云服務器記錄

阿里云服務器記錄 CentOS 8.4 64位 SCC版 CentOS 7.9 64位 SCC版 CentOS 7.9 64位 CentOS 7.9 64位 UEFI版 Alibaba Cloud Linux Anolis OS CentOS Windows Server Ubuntu Debian Fedora OpenSUSE Rocky Linux CentOS Stream AlmaLinux 阿里云服務器有個scc版,這個…

Flask+Mysql項目docker-compose部署(Pythondocker-compose詳細步驟)

一、前言 環境: Linux、docker、docker-compose、python(Flask)、Mysql 簡介: 簡單使用Flask框架寫的查詢Mysql數據接口,使用docker部署,shell腳本啟動 優勢: 采用docker方式部署更加便于維護,更加簡單快…

如何在Go中使用模板

引言 您是否需要以格式良好的輸出、文本報告或HTML頁面呈現一些數據?你可以使用Go模板來做到這一點。任何Go程序都可以使用text/template或html/template包(兩者都包含在Go標準庫中)來整齊地顯示數據。 這兩個包都允許你編寫文本模板并將數據傳遞給它們,以按你喜歡的格式呈…

“C語言“——scanf()、getchar() 、putchar()、之間的關系

scanf函數說明 scanf函數是對來自于標準輸入流的輸入數據作格式轉換,并將轉換結果保存至format后面的實參所指向的對象。 而const char*format 指向的字符串為格式控制字符串,它指定了可輸入的字符串以及賦值時轉換方法。 簡單來說給一個打印格式(輸入…

【并發編程篇】源碼分析,手動創建線程池

文章目錄 🛸前言🌹Executors的三大方法 🍔簡述線程池🎆手動創建線程池?源碼分析?代碼實現,手動創建線程池🎈CallerRunsPolicy()🎈AbortPolicy()🎈DiscardPolicy()🎈Dis…

LNPMariadb數據庫分離|web服務器集群

LNP&Mariadb數據庫分離|web服務器集群 網站架構演變單機版LNMP獨立數據庫服務器web服務器集群與Session保持 LNP與數據庫分離1. 準備一臺獨立的服務器,安裝數據庫軟件包2. 將之前的LNMP網站中的數據庫遷移到新的數據庫服務器3. 修改wordpress網站配置…

2023.12.24 關于 Redis 中 String 類型內部編碼 及 應用場景

目錄 String 類型內部編碼 3 種內部編碼方式 String 類型應用場景 Cache 緩存 鍵名命名規則 計數(Counter) 共享會話(Session ) 手機驗證碼 總結 String 類型內部編碼 3 種內部編碼方式 int:用來表示 64 位 —…

vue3菜單權限管理實現

前提 你的菜單是根據路由動態生成的,具體可以參考這篇博客對el-menu組件進行遞歸封裝(根據路由配置動態生成) 描述 首先將路由分為常量路由constantRoute(所有用戶都有的路由)和異步路由asyncRoute(需要動…

Gradle 插件

自定義Gradle插件 - 簡書

小天使的小難題:新生兒疝氣的關注與溫馨呵護

引言: 新生兒疝氣是一種在出生后可能出現的常見情況,雖然通常不會造成長期影響,但對于家長而言,了解如何正確應對新生兒疝氣是至關重要的。本文將深入探討新生兒疝氣的原因、癥狀,以及家長在面對這一問題時應該采取的…

1224. 交換瓶子(藍橋杯/圖論)

題目: 1224. 交換瓶子 - AcWing題庫 輸入樣例1: 5 3 1 2 5 4輸出樣例1: 3輸入樣例2: 5 5 4 3 2 1輸出樣例2: 2 思路:圖論 1.將對應的位置與當前的瓶子序列相連形成環。 2.最少交換次數能形成的最多…

Vue中的事件委托(事件代理)使用方法介紹

事件委托(事件代理) 將原本需要綁定在子元素上的事件監聽器委托在父元素上,讓父元素充當事件監聽的職務。 事件委托是一種利用事件冒泡的特性,在父節點上響應事件,而不是在子節點上響應事件的技術。它能夠改善性能&a…

如何理解JDK、JRE、JVM區別與聯系

摘要:JDK是 Java 語言的軟件開發工具包(SDK)。在JDK的安裝目錄下有一個jre目錄,里面有兩個文件夾bin和lib,在這里可以認為bin里的就是jvm,lib中則是jvm工作所需要的類庫,而jvm和 lib合起來就稱為jre。 一、JDK JDK(Ja…