可直接進(jìn)入網(wǎng)站的代碼網(wǎng)絡(luò)營銷策略實(shí)施的步驟
【Linux】網(wǎng)絡(luò)通信
文章目錄
- 【Linux】網(wǎng)絡(luò)通信
- 1、網(wǎng)絡(luò)基礎(chǔ)
- 1.1 計(jì)算機(jī)網(wǎng)絡(luò)
- 1.2 網(wǎng)絡(luò)模型
- TCP & UDP
- 1)IP地址
- 2)端口
- 3)TCP協(xié)議與UDP協(xié)議的比較
- 1.3 網(wǎng)絡(luò)傳輸
- 1.3.1 傳輸邏輯
- 1.3.2 傳輸條件
- 1.3.3 傳輸流程
- 1.4 地址管理
- 2、網(wǎng)絡(luò)編程
- 2.1 基本概念
- 2.1.1 IP地址
- 與協(xié)議關(guān)系
- 2.1.2 端口號(hào)
- 2.1.3 網(wǎng)絡(luò)字節(jié)序
- 2.2 基于TCP的socket通信
- 2.2.1 認(rèn)識(shí)socket
- 2.2.2 通信模型
- 2.2.3 服務(wù)端編寫
- 2.2.4 客戶端編寫
- 2.3 基于UDP
- 2.3.1 服務(wù)端實(shí)現(xiàn)
- 2.3.2 客戶端實(shí)現(xiàn)
1、網(wǎng)絡(luò)基礎(chǔ)
1.1 計(jì)算機(jī)網(wǎng)絡(luò)
計(jì)算機(jī)網(wǎng)絡(luò)的發(fā)展可以從獨(dú)立模式逐步演進(jìn)為網(wǎng)絡(luò)互連模式,這個(gè)過程可以分為以下幾個(gè)階段:
-
獨(dú)立模式:
在計(jì)算機(jī)網(wǎng)絡(luò)的早期階段,每臺(tái)計(jì)算機(jī)都是相對(duì)獨(dú)立的實(shí)體,沒有連接到其他計(jì)算機(jī)。每臺(tái)計(jì)算機(jī)僅用于單獨(dú)的任務(wù),數(shù)據(jù)和資源的共享非常有限。這個(gè)階段中,計(jì)算機(jī)主要用于科學(xué)計(jì)算和數(shù)據(jù)處理。 -
點(diǎn)對(duì)點(diǎn)連接:
隨著計(jì)算機(jī)數(shù)量的增加,人們開始意識(shí)到將計(jì)算機(jī)連接起來可以實(shí)現(xiàn)更高效的資源共享和通信。于是,點(diǎn)對(duì)點(diǎn)連接的網(wǎng)絡(luò)模式出現(xiàn)了,其中兩臺(tái)計(jì)算機(jī)通過專用的通信線路直接連接,可以進(jìn)行數(shù)據(jù)傳輸。這種模式在早期局域網(wǎng)中比較常見。 -
局域網(wǎng)(LAN)的興起:
隨著計(jì)算機(jī)數(shù)量的進(jìn)一步增加,局域網(wǎng)(LAN)開始興起。局域網(wǎng)允許位于同一地理位置的計(jì)算機(jī)互相連接,實(shí)現(xiàn)資源共享和通信。以太網(wǎng)技術(shù)的發(fā)展使得計(jì)算機(jī)可以通過共享的物理媒介(如同一根電纜)進(jìn)行通信,從而使局域網(wǎng)得以實(shí)現(xiàn)。 -
廣域網(wǎng)(WAN)的出現(xiàn):
隨著計(jì)算機(jī)網(wǎng)絡(luò)的發(fā)展,人們希望能夠跨越較大的地理范圍進(jìn)行通信。廣域網(wǎng)(WAN)應(yīng)運(yùn)而生,通過連接多個(gè)局域網(wǎng)和點(diǎn)對(duì)點(diǎn)連接,實(shí)現(xiàn)了更大范圍內(nèi)的計(jì)算機(jī)互連。這種網(wǎng)絡(luò)模式通過使用路由器和交換機(jī)來實(shí)現(xiàn)數(shù)據(jù)在不同網(wǎng)絡(luò)之間的傳輸。 -
互聯(lián)網(wǎng)的崛起:
互聯(lián)網(wǎng)是計(jì)算機(jī)網(wǎng)絡(luò)發(fā)展的最高階段。它將全球范圍內(nèi)的計(jì)算機(jī)網(wǎng)絡(luò)互相連接,實(shí)現(xiàn)了無縫的數(shù)據(jù)交換和資源共享?;ヂ?lián)網(wǎng)使用 TCP/IP 協(xié)議套件作為通信基礎(chǔ),允許不同類型的網(wǎng)絡(luò)和設(shè)備互相通信,從而形成了全球性的信息交流平臺(tái)。
1.2 網(wǎng)絡(luò)模型
計(jì)算機(jī)網(wǎng)絡(luò)模型是一種抽象框架,用于描述計(jì)算機(jī)網(wǎng)絡(luò)中各個(gè)組件之間的關(guān)系和通信方式。常見的計(jì)算機(jī)網(wǎng)絡(luò)模型有以下幾種:
-
OSI模型(開放系統(tǒng)互聯(lián)模型):
OSI模型是一個(gè)由國際標(biāo)準(zhǔn)化組織(ISO)制定的七層網(wǎng)絡(luò)模型,每一層都代表著特定的網(wǎng)絡(luò)功能。從下到上分別是物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層、會(huì)話層、表示層和應(yīng)用層。這個(gè)模型的主要目標(biāo)是促進(jìn)不同廠商開發(fā)的設(shè)備能夠相互通信。然而,實(shí)際上,大多數(shù)網(wǎng)絡(luò)采用的是下面提到的TCP/IP模型。 -
TCP/IP模型:
TCP/IP模型是實(shí)際上在互聯(lián)網(wǎng)上使用的模型,它由四個(gè)層次組成:網(wǎng)絡(luò)接口層、網(wǎng)絡(luò)層、傳輸層和應(yīng)用層。雖然層數(shù)較少,但它包含了與OSI模型中相似的功能。這個(gè)模型的名稱來自于它的兩個(gè)核心協(xié)議:傳輸控制協(xié)議(TCP)和Internet協(xié)議(IP)。 -
四層網(wǎng)絡(luò)模型:
有一些網(wǎng)絡(luò)模型將網(wǎng)絡(luò)分為四個(gè)層次:物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層和應(yīng)用層。這個(gè)模型省略了會(huì)話層、表示層和傳輸層,更簡化了網(wǎng)絡(luò)的結(jié)構(gòu)。 -
五層網(wǎng)絡(luò)模型:
這個(gè)模型將網(wǎng)絡(luò)分為五個(gè)層次:物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層和應(yīng)用層。它在功能上與TCP/IP模型相似,但只包含五個(gè)層次。

TCP/IP是一組協(xié)議的代名詞,它還包括許多協(xié)議,組成了TCP/IP協(xié)議簇。 TCP/IP協(xié)議簇分為四層,IP位于協(xié)議簇的第二層(對(duì)應(yīng)OSI的第三層),TCP位于協(xié)議簇的第三層 (對(duì)應(yīng)OSI的第四層)。TCP/IP通訊協(xié)議采用了4層的層級(jí)結(jié)構(gòu),每一層都呼叫它的下一層所提供 的網(wǎng)絡(luò)來完成自己的需求。這4層分別為:
- 應(yīng)用層:應(yīng)用程序間溝通的層,如簡單電子郵件傳輸(SMTP)、文件傳輸協(xié)議(FTP)、 網(wǎng)絡(luò)遠(yuǎn)程訪問協(xié)議(Telnet)等。
- 傳輸層:在此層中,它提供了節(jié)點(diǎn)間的數(shù)據(jù)傳送服務(wù),如傳輸控制協(xié)議(TCP)、 用戶數(shù)據(jù)報(bào)協(xié)議(UDP)等,TCP和UDP給數(shù)據(jù)包加入傳輸數(shù)據(jù)并把它傳輸?shù)较乱粚又?#xff0c; 這一層負(fù)責(zé)傳送數(shù)據(jù),并且確定數(shù)據(jù)已被送達(dá)并接收。
- 網(wǎng)絡(luò)互連層:負(fù)責(zé)提供基本的數(shù)據(jù)封包傳送功能,讓每一塊數(shù)據(jù)包都能夠到達(dá)目 的主機(jī)(但不檢查是否被正確接收),如網(wǎng)際協(xié)議(IP)。
- 主機(jī)到網(wǎng)絡(luò)層:對(duì)實(shí)際的網(wǎng)絡(luò)媒體的管理,定義如何使用實(shí)際網(wǎng)絡(luò) (如Ethernet、Serial Line等)來傳送數(shù)據(jù)。
TCP & UDP
1)IP地址
2)端口
1. 用于區(qū)分不同的應(yīng)用程序
2. 端口號(hào)的范圍為0-65535,其中0-1023未系統(tǒng)的保留端口,我們的程序盡可能別使用這些端口!
3. IP地址和端口號(hào)組成了我們的Socket,Socket是網(wǎng)絡(luò)運(yùn)行程序間雙向通信鏈路的終結(jié)點(diǎn), 是TCP和UDP的基礎(chǔ)!
4. 常用協(xié)議使用的端口:HTTP:80,FTP:21,TELNET:23
3)TCP協(xié)議與UDP協(xié)議的比較
TCP協(xié)議流程詳解:
首先TCP/IP是一個(gè)協(xié)議簇,里面包括很多協(xié)議的。UDP只是其中的一個(gè)。之所以命名為TCP/IP協(xié)議, 因?yàn)門CP,IP協(xié)議是兩個(gè)很重要的協(xié)議,就用他兩命名了。
下面我們來講解TCP協(xié)議和UDP協(xié)議的區(qū)別:
TCP(Transmission Control Protocol,傳輸控制協(xié)議)是面向連接的協(xié)議,即在收發(fā)數(shù)據(jù)錢 ,都需要與對(duì)面建立可靠的鏈接,這也是面試經(jīng)常會(huì)問到的TCP的三次握手以及TCP的四次揮手! 三次握手: 建立一個(gè)TCP連接時(shí),需要客戶端和服務(wù)端總共發(fā)送3個(gè)包以確認(rèn)連接的建立, 在Socket編程中,這一過程由客戶端執(zhí)行connect來觸發(fā),具體流程圖如下:
- 第一次握手:Client將標(biāo)志位SYN置為1,隨機(jī)產(chǎn)生一個(gè)值seq=J,并將該數(shù)據(jù)包發(fā)送給Server, Client進(jìn)入SYN_SENT狀態(tài),等待Server確認(rèn)。
- 第二次握手:Server收到數(shù)據(jù)包后由標(biāo)志位SYN=1知道Client請(qǐng)求建立連接,Server將標(biāo)志位 SYN和ACK都置為1,ack=J+1,隨機(jī)產(chǎn)生一個(gè)值seq=K,并將該數(shù)據(jù)包發(fā)送給Client以確認(rèn)連接請(qǐng)求 ,Server進(jìn)入SYN_RCVD狀態(tài)。
- 第三次握手:Client收到確認(rèn)后,檢查ack是否為J+1,ACK是否為1,如果正確則將標(biāo)志位ACK 置為1,ack=K+1,并將該數(shù)據(jù)包發(fā)送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則 連接建立成功,Client和Server進(jìn)入ESTABLISHED狀態(tài),完成三次握手,隨后Client與Server之間可以 開始傳輸數(shù)據(jù)了。
- 四次揮手: 終止TCP連接,就是指斷開一個(gè)TCP連接時(shí),需要客戶端和服務(wù)端總共發(fā)送4個(gè)包以確認(rèn)連接的斷開。 在Socket編程中,這一過程由客戶端或服務(wù)端任一方執(zhí)行close來觸發(fā),具體流程圖如下:
- 第一次揮手:Client發(fā)送一個(gè)FIN,用來關(guān)閉Client到Server的數(shù)據(jù)傳送,Client進(jìn)入 FIN_WAIT_1狀態(tài)
- 第二次揮手:Server收到FIN后,發(fā)送一個(gè)ACK給Client,確認(rèn)序號(hào)為收到序號(hào)+1(與SYN相同, 一個(gè)FIN占用一個(gè)序號(hào)),Server進(jìn)入CLOSE_WAIT狀態(tài)。
- 第三次揮手:Server發(fā)送一個(gè)FIN,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進(jìn)入LAST_ACK 狀態(tài)。
- 第四次揮手:Client收到FIN后,Client進(jìn)入TIME_WAIT狀態(tài),接著發(fā)送一個(gè)ACK給Server,確認(rèn)序號(hào)為收到序號(hào)+1,Server進(jìn)入CLOSED狀態(tài),完成四次揮手。 另外也可能是同時(shí)發(fā)起主動(dòng)關(guān)閉的情況:
另外還可能有一個(gè)常見的問題就是:為什么建立連接是三次握手,而關(guān)閉連接卻是四次揮手呢? 答:因?yàn)榉?wù)端在LISTEN狀態(tài)下,收到建立連接請(qǐng)求的SYN報(bào)文后,把ACK和SYN放在一個(gè)報(bào)文里 發(fā)送給客戶端。而關(guān)閉連接時(shí),當(dāng)收到對(duì)方的FIN報(bào)文時(shí),僅僅表示對(duì)方不再發(fā)送數(shù)據(jù)了但是還 能接收數(shù)據(jù),己方也未必全部數(shù)據(jù)都發(fā)送給對(duì)方了,所以己方可以立即close,也可以發(fā)送一些 數(shù)據(jù)給對(duì)方后,再發(fā)送FIN報(bào)文給對(duì)方來表示同意現(xiàn)在關(guān)閉連接,因此,己方ACK和FIN一般都會(huì)分開發(fā)送。
UDP協(xié)議詳解:
UDP(User Datagram Protocol)用戶數(shù)據(jù)報(bào)協(xié)議,非連接的協(xié)議,傳輸數(shù)據(jù)之前源端和終端不 建立連接,當(dāng)它想傳送時(shí)就簡單地去抓取來自應(yīng)用程序的數(shù)據(jù),并盡可能快地把它扔到網(wǎng)絡(luò)上。 在發(fā)送端,UDP傳送數(shù)據(jù)的速度僅僅是受應(yīng)用程序生成數(shù)據(jù)的速度、計(jì)算機(jī)的能力和傳輸帶寬 的限制;在接收端,UDP把每個(gè)消息段放在隊(duì)列中,應(yīng)用程序每次從隊(duì)列中讀一個(gè)消息段。 相比TCP就是無需建立鏈接,結(jié)構(gòu)簡單,無法保證正確性,容易丟包
1.3 網(wǎng)絡(luò)傳輸
網(wǎng)絡(luò)傳輸和網(wǎng)絡(luò)模型之間存在密切的聯(lián)系,網(wǎng)絡(luò)模型為網(wǎng)絡(luò)傳輸提供了一種結(jié)構(gòu)化的框架和指導(dǎo)原則,幫助理解和組織網(wǎng)絡(luò)中的數(shù)據(jù)傳輸過程。
TCP/IP協(xié)議簇是一組協(xié)議,它包括物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、傳輸層和應(yīng)用層五個(gè)層次。每一層都有特定的功能和任務(wù):
-
物理層:負(fù)責(zé)傳輸光/電信號(hào),包括以太網(wǎng)、光纖、無線網(wǎng)絡(luò)等。集線器工作在此層。
-
數(shù)據(jù)鏈路層:傳送和識(shí)別數(shù)據(jù)幀,處理幀同步、沖突檢測、數(shù)據(jù)差錯(cuò)校驗(yàn)。交換機(jī)工作在此層。
-
網(wǎng)絡(luò)層:進(jìn)行地址管理和路由選擇,通過IP地址標(biāo)識(shí)主機(jī),并規(guī)劃數(shù)據(jù)傳輸路徑。路由器工作在此層。
-
傳輸層:負(fù)責(zé)主機(jī)間數(shù)據(jù)傳輸,如TCP協(xié)議確保數(shù)據(jù)可靠傳輸。
-
應(yīng)用層:處理應(yīng)用程序間的通信,如電子郵件傳輸(SMTP)、文件傳輸(FTP)、遠(yuǎn)程訪問(Telnet)等。
這五層結(jié)構(gòu)協(xié)同工作,構(gòu)成了TCP/IP協(xié)議簇,支撐了現(xiàn)代計(jì)算機(jī)網(wǎng)絡(luò)的各項(xiàng)通信和數(shù)據(jù)傳輸功能。
對(duì)于一臺(tái)主機(jī), 它的操作系統(tǒng)內(nèi)核實(shí)現(xiàn)了從傳輸層到物理層的內(nèi)容
對(duì)于一臺(tái)路由器, 它實(shí)現(xiàn)了從網(wǎng)絡(luò)層到物理層
對(duì)于一臺(tái)交換機(jī), 它實(shí)現(xiàn)了從數(shù)據(jù)鏈路層到物理層
對(duì)于集線器, 它只實(shí)現(xiàn)了物理層
1.3.1 傳輸邏輯
數(shù)據(jù)傳輸?shù)倪壿嬁梢詺w納如下:
-
準(zhǔn)備階段:
- 在應(yīng)用層,準(zhǔn)備要傳輸?shù)臄?shù)據(jù),定義數(shù)據(jù)格式和處理邏輯。
- 選擇適當(dāng)?shù)膽?yīng)用層協(xié)議,如HTTP、FTP等,以確定數(shù)據(jù)的傳輸方式和規(guī)則。
-
傳輸層協(xié)議選擇:
- 根據(jù)應(yīng)用需求選擇傳輸層協(xié)議,如可靠性要求高則選擇TCP,實(shí)時(shí)性要求高則選擇UDP。
-
建立連接和監(jiān)聽:
- 對(duì)于TCP,建立連接是必要的。發(fā)送端和接收端之間建立連接,以確保數(shù)據(jù)的可靠傳輸。
- 對(duì)于UDP,連接不是必需的,但需要確定數(shù)據(jù)發(fā)送和接收的目標(biāo)地址。
-
數(shù)據(jù)封裝和加頭部信息:
- 在發(fā)送端,將應(yīng)用層數(shù)據(jù)封裝為數(shù)據(jù)包,并添加適當(dāng)?shù)膫鬏攲雍途W(wǎng)絡(luò)層頭部信息。
- 頭部信息包括IP地址、端口號(hào)等,用于路由和目標(biāo)設(shè)備的標(biāo)識(shí)。
-
數(shù)據(jù)傳輸:
- 傳輸層協(xié)議負(fù)責(zé)將封裝后的數(shù)據(jù)包傳輸?shù)侥繕?biāo)設(shè)備,同時(shí)執(zhí)行錯(cuò)誤檢測、流量控制等操作。
- 網(wǎng)絡(luò)層協(xié)議根據(jù)目標(biāo)IP地址選擇適當(dāng)?shù)穆酚?#xff0c;確定數(shù)據(jù)包的傳輸路徑。
-
物理傳輸:
- 鏈路層將數(shù)據(jù)包封裝為幀,添加鏈路層頭部和尾部,通過物理介質(zhì)傳輸?shù)浇邮斩恕?/li>
-
數(shù)據(jù)解封和處理:
- 在接收端,鏈路層接收幀并解析,將數(shù)據(jù)交給網(wǎng)絡(luò)層。
- 網(wǎng)絡(luò)層根據(jù)IP地址確定目標(biāo)設(shè)備,將數(shù)據(jù)交給傳輸層。
-
數(shù)據(jù)重組和解析:
- 傳輸層協(xié)議負(fù)責(zé)將接收到的數(shù)據(jù)包按序重組,執(zhí)行錯(cuò)誤檢測和糾正,將數(shù)據(jù)交給應(yīng)用層。
-
應(yīng)用層處理:
- 應(yīng)用程序解析數(shù)據(jù)包,根據(jù)定義的數(shù)據(jù)格式處理數(shù)據(jù)內(nèi)容,執(zhí)行相應(yīng)的業(yè)務(wù)邏輯。
這個(gè)邏輯流程涵蓋了數(shù)據(jù)傳輸從應(yīng)用層到物理層的各個(gè)階段和過程,確保數(shù)據(jù)能夠按照一定的規(guī)則和流程進(jìn)行傳輸和處理。
1.3.2 傳輸條件
將數(shù)據(jù)傳輸?shù)谋貍錀l件按照應(yīng)用層、傳輸層、網(wǎng)絡(luò)層和鏈路層進(jìn)行分類如下:
應(yīng)用層:
- 通信設(shè)備:需要至少兩臺(tái)通信設(shè)備。
- IP地址和端口號(hào):每臺(tái)設(shè)備需要唯一的IP地址和適當(dāng)?shù)亩丝谔?hào)。
- 數(shù)據(jù)格式定義:需要定義數(shù)據(jù)的格式,以便發(fā)送方和接收方正確解析和處理數(shù)據(jù)。
- 安全性考慮:需要考慮數(shù)據(jù)的安全性和加密,特別是對(duì)于敏感信息的傳輸。
傳輸層:
- 協(xié)議選擇:需要選擇適當(dāng)?shù)膫鬏攲訁f(xié)議,如TCP或UDP,根據(jù)數(shù)據(jù)傳輸需求進(jìn)行選擇。
- 傳輸機(jī)制:需要了解如何建立連接、傳輸數(shù)據(jù)、管理流量和關(guān)閉連接等操作。
- 錯(cuò)誤處理機(jī)制:需要考慮數(shù)據(jù)傳輸中可能發(fā)生的錯(cuò)誤情況,如丟包、重傳等。
網(wǎng)絡(luò)層:
- 網(wǎng)絡(luò)連接:通信設(shè)備需要通過網(wǎng)絡(luò)連接在一起,可以是有線或無線連接。
- IP地址:每臺(tái)設(shè)備需要唯一的IP地址,用于在網(wǎng)絡(luò)中標(biāo)識(shí)設(shè)備。
- 路由選擇:需要使用路由協(xié)議選擇數(shù)據(jù)包的傳輸路徑。
鏈路層:
- 物理連接:通信設(shè)備需要通過物理層面的連接,如以太網(wǎng)、無線電波等。
- 鏈路地址:鏈路層需要確定每個(gè)設(shè)備的物理地址,如MAC地址。
1.3.3 傳輸流程
日常生活中發(fā)送電子郵件時(shí),TCP/IP協(xié)議傳輸?shù)木唧w流程如下表所示:
步驟 | 層次 | 動(dòng)作與報(bào)頭 |
---|---|---|
1 | 應(yīng)用層 | 編寫郵件,準(zhǔn)備郵件內(nèi)容。 |
2 | 應(yīng)用層 | 使用電子郵件客戶端。 |
3 | 應(yīng)用層 | 封裝郵件數(shù)據(jù)。 |
4 | 傳輸層 | 選擇TCP協(xié)議。 |
5 | 傳輸層 | 建立TCP連接。 |
6 | 傳輸層 | 封裝郵件數(shù)據(jù)為TCP數(shù)據(jù)包。 |
7 | 網(wǎng)絡(luò)層 | 選擇IP地址。 |
8 | 網(wǎng)絡(luò)層 | 封裝TCP數(shù)據(jù)包為IP數(shù)據(jù)包。 |
9 | 鏈路層 | 分幀和添加鏈路層頭部。 |
10 | 鏈路層 | 通過物理介質(zhì)傳輸數(shù)據(jù)。 |
11 | 鏈路層 | 解析數(shù)據(jù)幀,移除鏈路層頭部。 |
12 | 網(wǎng)絡(luò)層 | 解析IP數(shù)據(jù)包,獲取目標(biāo)IP。 |
13 | 傳輸層 | TCP重組和校驗(yàn)數(shù)據(jù)包。 |
14 | 傳輸層 | 將數(shù)據(jù)包傳遞給應(yīng)用層。 |
15 | 應(yīng)用層 | 解析郵件數(shù)據(jù),處理郵件內(nèi)容。 |
16 | 應(yīng)用層 | 繼續(xù)處理郵件,可能轉(zhuǎn)發(fā)。 |
1.4 地址管理
網(wǎng)絡(luò)地址是為了在計(jì)算機(jī)網(wǎng)絡(luò)中標(biāo)識(shí)不同設(shè)備和主機(jī)而存在的。不同層次的網(wǎng)絡(luò)模型在數(shù)據(jù)傳輸過程中都需要使用網(wǎng)絡(luò)地址來確定數(shù)據(jù)的發(fā)送和接收方。
-
物理層:物理層負(fù)責(zé)信號(hào)傳輸,但為了確保信號(hào)到達(dá)正確的設(shè)備,每個(gè)設(shè)備都需要在網(wǎng)絡(luò)中有唯一的物理地址,即MAC地址。這是一個(gè)在數(shù)據(jù)鏈路層中使用的地址,用于在局域網(wǎng)中識(shí)別設(shè)備。
-
數(shù)據(jù)鏈路層:在數(shù)據(jù)鏈路層,數(shù)據(jù)幀需要帶有目標(biāo)MAC地址和源MAC地址,以便設(shè)備可以正確地發(fā)送和接收數(shù)據(jù)。這些地址用于在局域網(wǎng)內(nèi)識(shí)別設(shè)備。
-
網(wǎng)絡(luò)層:在網(wǎng)絡(luò)層,IP地址被用來標(biāo)識(shí)不同的主機(jī)和路由器。IP地址用于在全球范圍內(nèi)尋找目標(biāo)設(shè)備,使數(shù)據(jù)能夠跨越不同網(wǎng)絡(luò)進(jìn)行傳輸。
-
傳輸層:在傳輸層,數(shù)據(jù)包含源端口號(hào)和目標(biāo)端口號(hào)。這些端口號(hào)一起構(gòu)成了一個(gè)套接字,用于標(biāo)識(shí)不同的應(yīng)用程序和服務(wù)。它們幫助傳輸層將數(shù)據(jù)傳遞給正確的應(yīng)用程序。
總之,地址在不同的網(wǎng)絡(luò)層中扮演著關(guān)鍵的角色,用于標(biāo)識(shí)不同的設(shè)備、主機(jī)和服務(wù)。它們幫助確保數(shù)據(jù)在網(wǎng)絡(luò)中正確傳輸,并使通信能夠順利進(jìn)行。
2、網(wǎng)絡(luò)編程
2.1 基本概念
2.1.1 IP地址
IP地址(Internet Protocol Address)是用于在計(jì)算機(jī)網(wǎng)絡(luò)中唯一標(biāo)識(shí)和定位設(shè)備的數(shù)字標(biāo)簽。它是Internet協(xié)議族的一部分,用于在網(wǎng)絡(luò)中進(jìn)行數(shù)據(jù)包的路由和傳遞。IP地址充當(dāng)了類似于郵寄地址的作用,以確保數(shù)據(jù)能夠準(zhǔn)確地從發(fā)送者傳遞到接收者。
以下是IP地址的基本概念:
-
唯一標(biāo)識(shí)性: 每個(gè)設(shè)備(如計(jì)算機(jī)、服務(wù)器、路由器、移動(dòng)設(shè)備等)在網(wǎng)絡(luò)中都被分配了一個(gè)唯一的IP地址。這有助于確保數(shù)據(jù)包能夠正確地路由和傳遞。
-
分層結(jié)構(gòu): IP地址通常被分為兩個(gè)主要版本:IPv4(Internet Protocol version 4)和IPv6(Internet Protocol version 6)。IPv4使用32位二進(jìn)制數(shù)表示,通常以點(diǎn)分十進(jìn)制表示法(例如,192.168.1.1)呈現(xiàn)。IPv6使用128位二進(jìn)制數(shù)表示,以一種更復(fù)雜的方式顯示(例如,2001:0db8:85a3:0000:0000:8a2e:0370:7334)。
-
IPv4地址枯竭: 由于互聯(lián)網(wǎng)的迅速擴(kuò)展,IPv4地址空間已經(jīng)基本上耗盡。這導(dǎo)致了IPv6的引入,因?yàn)樗峁┝烁蟮牡刂房臻g,能夠支持未來更多的互聯(lián)設(shè)備。
-
公共和私有地址: IP地址可以是公共的或私有的。公共IP地址是全球范圍內(nèi)唯一的,用于直接訪問互聯(lián)網(wǎng)。私有IP地址在局域網(wǎng)(例如家庭或企業(yè)內(nèi)部網(wǎng)絡(luò))中使用,不直接暴露給互聯(lián)網(wǎng)。
-
子網(wǎng)掩碼: 子網(wǎng)掩碼是與IP地址結(jié)合使用的參數(shù),用于指示哪些部分是網(wǎng)絡(luò)部分,哪些部分是主機(jī)部分。它有助于將IP地址劃分為網(wǎng)絡(luò)和主機(jī),以便在子網(wǎng)內(nèi)進(jìn)行更有效的路由。
-
DHCP和靜態(tài)IP: IP地址可以通過動(dòng)態(tài)主機(jī)配置協(xié)議(DHCP)自動(dòng)分配,也可以手動(dòng)配置為靜態(tài)IP地址。DHCP允許網(wǎng)絡(luò)設(shè)備在加入網(wǎng)絡(luò)時(shí)自動(dòng)獲取IP地址和其他網(wǎng)絡(luò)配置信息。
-
網(wǎng)絡(luò)層地址: IP地址位于網(wǎng)絡(luò)層(第三層)協(xié)議中,負(fù)責(zé)將數(shù)據(jù)包從源主機(jī)傳輸?shù)侥繕?biāo)主機(jī)。它與MAC地址(在數(shù)據(jù)鏈路層,第二層)一起協(xié)作,以實(shí)現(xiàn)數(shù)據(jù)在不同網(wǎng)絡(luò)之間的傳遞。
IP地址是互聯(lián)網(wǎng)通信的基礎(chǔ),通過它,數(shù)據(jù)能夠在全球范圍內(nèi)進(jìn)行準(zhǔn)確和可靠的傳遞。不論是瀏覽網(wǎng)頁、發(fā)送電子郵件還是進(jìn)行視頻通話,IP地址在背后都發(fā)揮著至關(guān)重要的作用。
與協(xié)議關(guān)系
IP地址是互聯(lián)網(wǎng)協(xié)議族中的一個(gè)關(guān)鍵概念,它與其他多個(gè)協(xié)議相互配合,以實(shí)現(xiàn)數(shù)據(jù)在網(wǎng)絡(luò)中的傳輸和通信。以下是IP地址與其他一些重要協(xié)議之間的關(guān)系:
-
TCP/IP協(xié)議棧: TCP/IP是一組網(wǎng)絡(luò)協(xié)議,它們一起構(gòu)成了互聯(lián)網(wǎng)的基礎(chǔ)。IP地址是TCP/IP協(xié)議棧中的核心組成部分。TCP(Transmission Control Protocol)負(fù)責(zé)在通信雙方建立可靠的連接和數(shù)據(jù)傳輸,而IP則負(fù)責(zé)將數(shù)據(jù)包從源主機(jī)路由到目標(biāo)主機(jī)。
-
MAC地址: MAC地址(Media Access Control Address)是數(shù)據(jù)鏈路層(第二層)的一個(gè)標(biāo)識(shí)符,用于在局域網(wǎng)中唯一標(biāo)識(shí)網(wǎng)絡(luò)設(shè)備。IP地址(位于網(wǎng)絡(luò)層,第三層)與MAC地址相互配合,通過ARP(Address Resolution Protocol)等機(jī)制,將IP地址映射到對(duì)應(yīng)的MAC地址,以實(shí)現(xiàn)數(shù)據(jù)在局域網(wǎng)內(nèi)的傳輸。
-
ARP協(xié)議: ARP(Address Resolution Protocol)用于將IP地址解析為對(duì)應(yīng)的MAC地址。當(dāng)設(shè)備需要發(fā)送數(shù)據(jù)到另一個(gè)設(shè)備時(shí),需要知道目標(biāo)設(shè)備的MAC地址。ARP協(xié)議幫助主機(jī)在同一局域網(wǎng)中查找IP地址對(duì)應(yīng)的MAC地址。
-
DHCP協(xié)議: DHCP(Dynamic Host Configuration Protocol)用于自動(dòng)分配IP地址和其他網(wǎng)絡(luò)配置信息給新加入網(wǎng)絡(luò)的設(shè)備。DHCP服務(wù)器分配可用的IP地址給客戶端,使設(shè)備能夠快速連接網(wǎng)絡(luò)而不需要手動(dòng)配置IP地址。
-
DNS協(xié)議: DNS(Domain Name System)將易于記憶的域名轉(zhuǎn)換為IP地址。在互聯(lián)網(wǎng)上,人們更容易記住域名(如www.example.com),而不是復(fù)雜的IP地址。DNS協(xié)議允許將域名解析為相應(yīng)的IP地址,使得用戶能夠訪問網(wǎng)站和資源。
-
ICMP協(xié)議: ICMP(Internet Control Message Protocol)用于在IP網(wǎng)絡(luò)中傳遞錯(cuò)誤消息和控制消息。例如,當(dāng)數(shù)據(jù)包在傳輸過程中發(fā)生問題時(shí),ICMP可以生成錯(cuò)誤消息并通知源主機(jī)。
這些協(xié)議相互合作,共同構(gòu)成了互聯(lián)網(wǎng)通信的基礎(chǔ)架構(gòu)。IP地址在這些協(xié)議之間扮演著橋梁的角色,使得數(shù)據(jù)能夠在不同層級(jí)的網(wǎng)絡(luò)中傳輸和交換。
2.1.2 端口號(hào)
在計(jì)算機(jī)網(wǎng)絡(luò)中,端口號(hào)是用于標(biāo)識(shí)特定應(yīng)用程序或服務(wù)的數(shù)字標(biāo)識(shí)符。它是在傳輸層協(xié)議中使用的概念,例如在TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)中。通過將IP地址與端口號(hào)結(jié)合使用,網(wǎng)絡(luò)中的不同應(yīng)用程序可以在同一設(shè)備上同時(shí)運(yùn)行,實(shí)現(xiàn)數(shù)據(jù)的多路復(fù)用和分發(fā)。
以下是端口號(hào)的一些關(guān)鍵含義:
-
標(biāo)識(shí)應(yīng)用程序: 端口號(hào)用于標(biāo)識(shí)在一個(gè)設(shè)備上運(yùn)行的不同應(yīng)用程序或服務(wù)。每個(gè)應(yīng)用程序可以監(jiān)聽一個(gè)或多個(gè)特定的端口號(hào),以便與其他設(shè)備通信。
-
多路復(fù)用: 通過使用端口號(hào),多個(gè)應(yīng)用程序可以在同一設(shè)備上同時(shí)運(yùn)行,而無需相互干擾。傳輸層協(xié)議可以根據(jù)目標(biāo)端口號(hào)將數(shù)據(jù)包傳遞給正確的應(yīng)用程序。
-
數(shù)據(jù)傳輸: 端口號(hào)與IP地址一起構(gòu)成了網(wǎng)絡(luò)套接字(socket),從而允許應(yīng)用程序通過網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)傳輸。發(fā)送端使用源端口號(hào),接收端使用目標(biāo)端口號(hào),以確定數(shù)據(jù)應(yīng)該交付給哪個(gè)應(yīng)用程序。
-
服務(wù)識(shí)別: 一些標(biāo)準(zhǔn)端口號(hào)已經(jīng)被分配給特定的服務(wù)或協(xié)議。例如,HTTP通常使用端口號(hào)80,HTTPS使用端口號(hào)443,SMTP(郵件傳輸)使用端口號(hào)25等。這樣,網(wǎng)絡(luò)設(shè)備和應(yīng)用程序可以識(shí)別常見的服務(wù)并將數(shù)據(jù)傳遞給正確的端口。
-
安全性: 端口號(hào)也與網(wǎng)絡(luò)安全有關(guān)。防火墻和網(wǎng)絡(luò)安全設(shè)備可以基于端口號(hào)來控制數(shù)據(jù)流量,允許或阻止特定的應(yīng)用程序或服務(wù)通信。
-
動(dòng)態(tài)分配: 除了一些常見的標(biāo)準(zhǔn)端口號(hào)外,應(yīng)用程序也可以使用動(dòng)態(tài)分配的端口號(hào)。這些端口號(hào)在通信過程中臨時(shí)分配給應(yīng)用程序,以便在通信結(jié)束后可以被釋放并重新使用。
端口號(hào)是網(wǎng)絡(luò)通信中的一個(gè)重要概念,它使得不同的應(yīng)用程序能夠在同一設(shè)備上通過網(wǎng)絡(luò)進(jìn)行通信,并確保數(shù)據(jù)能夠準(zhǔn)確傳遞到目標(biāo)應(yīng)用程序。
2.1.3 網(wǎng)絡(luò)字節(jié)序
網(wǎng)絡(luò)字節(jié)序(Network Byte Order)是在討論在計(jì)算機(jī)網(wǎng)絡(luò)中跨不同計(jì)算機(jī)體系結(jié)構(gòu)(如大端序和小端序)傳輸數(shù)據(jù)時(shí)的字節(jié)順序問題。不同的計(jì)算機(jī)體系結(jié)構(gòu)在內(nèi)存中以不同的方式存儲(chǔ)多字節(jié)數(shù)據(jù)(如整數(shù)、浮點(diǎn)數(shù)等)的字節(jié)順序,這可能導(dǎo)致在網(wǎng)絡(luò)通信中數(shù)據(jù)的混淆和解釋錯(cuò)誤。
網(wǎng)絡(luò)通信涉及多臺(tái)計(jì)算機(jī)或設(shè)備之間的數(shù)據(jù)交換。如果不同的設(shè)備使用不同的字節(jié)序,那么在發(fā)送數(shù)據(jù)時(shí)可能會(huì)導(dǎo)致以下問題:
-
數(shù)據(jù)解釋錯(cuò)誤: 接收方可能會(huì)錯(cuò)誤地解釋數(shù)據(jù),因?yàn)樽止?jié)的順序與發(fā)送方不同。這會(huì)導(dǎo)致數(shù)據(jù)在接收方的應(yīng)用程序中被錯(cuò)誤地解釋和處理。
-
數(shù)據(jù)截?cái)?#xff1a; 如果數(shù)據(jù)在發(fā)送和接收時(shí)以不同的字節(jié)序傳輸,可能會(huì)導(dǎo)致數(shù)據(jù)的部分截?cái)嗷騺G失。這會(huì)損壞數(shù)據(jù)的完整性。
為了解決這些問題,網(wǎng)絡(luò)通信需要使用一種一致的字節(jié)序,以確保數(shù)據(jù)可以在不同設(shè)備之間正確傳遞和解釋。這種一致的字節(jié)序被稱為網(wǎng)絡(luò)字節(jié)序,通常采用大端字節(jié)序。
網(wǎng)絡(luò)字節(jié)序的討論涉及如何在數(shù)據(jù)傳輸過程中,確保發(fā)送和接收雙方都能正確地解釋數(shù)據(jù)。為了實(shí)現(xiàn)這一點(diǎn),需要使用字節(jié)序轉(zhuǎn)換函數(shù)(如htonl()
、htons()
、ntohl()
和ntohs()
)來在不同字節(jié)序之間進(jìn)行轉(zhuǎn)換。這樣可以確保數(shù)據(jù)在網(wǎng)絡(luò)中的傳輸和解釋是一致的,無論使用的是大端序還是小端序。
2.2 基于TCP的socket通信
2.2.1 認(rèn)識(shí)socket
Socket(套接字)是一種用于在計(jì)算機(jī)網(wǎng)絡(luò)中進(jìn)行通信的編程接口(API)。它提供了一種機(jī)制,使得不同計(jì)算機(jī)之間可以通過網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)傳輸,實(shí)現(xiàn)進(jìn)程間的通信。
背景和問題: 在早期的計(jì)算機(jī)網(wǎng)絡(luò)中,需要一種方法來在不同設(shè)備之間進(jìn)行通信。最初的網(wǎng)絡(luò)通信是通過低層的網(wǎng)絡(luò)協(xié)議進(jìn)行的,但這對(duì)于應(yīng)用程序來說過于繁瑣。開發(fā)人員需要一種更高層次的抽象來處理通信細(xì)節(jié),從而實(shí)現(xiàn)應(yīng)用程序之間的數(shù)據(jù)交換。
解決問題和方法: Socket接口的出現(xiàn)解決了上述問題。它提供了一種標(biāo)準(zhǔn)的API,使得應(yīng)用程序可以方便地創(chuàng)建、連接、發(fā)送和接收數(shù)據(jù)。通過Socket,應(yīng)用程序不需要關(guān)心底層的網(wǎng)絡(luò)細(xì)節(jié),而只需要使用Socket函數(shù)來實(shí)現(xiàn)通信。
作用: Socket在網(wǎng)絡(luò)通信中起到了關(guān)鍵作用,它使得應(yīng)用程序能夠輕松地在不同設(shè)備之間進(jìn)行數(shù)據(jù)交換。通過Socket,開發(fā)人員可以構(gòu)建各種網(wǎng)絡(luò)應(yīng)用,如網(wǎng)絡(luò)游戲、聊天應(yīng)用、文件傳輸工具、網(wǎng)絡(luò)服務(wù)器等。
發(fā)展過程和變化: Socket的發(fā)展經(jīng)歷了不同的階段。起初,它是基于傳統(tǒng)的Unix文件I/O,后來隨著計(jì)算機(jī)網(wǎng)絡(luò)的發(fā)展,Socket逐漸被標(biāo)準(zhǔn)化,出現(xiàn)了不同的Socket類型(如流套接字、數(shù)據(jù)報(bào)套接字等)和Socket函數(shù)(如socket()、bind()、connect()、send()、recv()等)。隨著網(wǎng)絡(luò)技術(shù)的進(jìn)步,Socket在不同操作系統(tǒng)和編程語言中得到了廣泛支持。
此外,隨著互聯(lián)網(wǎng)的迅速發(fā)展,Socket的應(yīng)用范圍變得更加廣泛,從傳統(tǒng)的網(wǎng)絡(luò)通信延伸到了Web開發(fā)、實(shí)時(shí)音視頻傳輸、云計(jì)算等領(lǐng)域。同時(shí),各種高級(jí)通信協(xié)議也在Socket基礎(chǔ)上構(gòu)建,如HTTP、FTP、SMTP等。
總之,Socket是網(wǎng)絡(luò)編程中的核心概念,它在計(jì)算機(jī)網(wǎng)絡(luò)通信中扮演了極其重要的角色,提供了一種通用的接口,使得應(yīng)用程序可以方便地進(jìn)行跨網(wǎng)絡(luò)通信,不需要處理底層細(xì)節(jié)。從最初的Unix文件I/O發(fā)展到現(xiàn)代的網(wǎng)絡(luò)通信,Socket一直在不斷演進(jìn),適應(yīng)不斷變化的網(wǎng)絡(luò)需求。
2.2.2 通信模型
Socket通信實(shí)現(xiàn)步驟解析:
Step 1:創(chuàng)建ServerSocket和Socket
Step 2:打開連接到的Socket的輸入/輸出流
Step 3:按照協(xié)議對(duì)Socket進(jìn)行讀/寫操作
Step 4:關(guān)閉輸入輸出流,以及Socket
接下來寫一個(gè)簡單的例子,開啟服務(wù)端后,客戶端點(diǎn)擊按鈕然后鏈接服務(wù)端, 并向服務(wù)端發(fā)送一串字符串,表示通過Socket鏈接上服務(wù)器
2.2.3 服務(wù)端編寫
服務(wù)端要做的事有這些:
Step 1:創(chuàng)建ServerSocket對(duì)象,綁定監(jiān)聽的端口
Step 2:調(diào)用accept()方法監(jiān)聽客戶端的請(qǐng)求
Step 3:連接建立后,通過輸入流讀取客戶端發(fā)送的請(qǐng)求信息
Step 4:通過輸出流向客戶端發(fā)送響應(yīng)信息
Step 5:關(guān)閉相關(guān)資源
代碼實(shí)現(xiàn):
#include <iostream>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {int serverSocket, clientSocket;struct sockaddr_in serverAddr;struct sockaddr_in clientAddr;socklen_t clientAddrLen = sizeof(clientAddr);// 1. 創(chuàng)建服務(wù)器端 SocketserverSocket = socket(AF_INET, SOCK_STREAM, 0);// 配置服務(wù)器地址memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = INADDR_ANY; // 任意地址serverAddr.sin_port = htons(12345); // 端口號(hào)轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序// 2. 綁定端口和地址bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));// 3. 監(jiān)聽連接請(qǐng)求listen(serverSocket, 5); // 允許最大排隊(duì)連接數(shù)為5std::cout << "~~~ 服務(wù)端已就緒,等待客戶端接入 ~~~" << std::endl;// 4. 等待客戶端連接clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);char clientIp[INET_ADDRSTRLEN];inet_ntop(AF_INET, &(clientAddr.sin_addr), clientIp, INET_ADDRSTRLEN);std::cout << "客戶端接入,客戶端 IP 地址:" << clientIp << std::endl;// 5. 讀取客戶端信息char buffer[1024];memset(buffer, 0, sizeof(buffer));while (recv(clientSocket, buffer, sizeof(buffer), 0) > 0) {std::cout << "客戶端發(fā)送過來的信息:" << buffer << std::endl;memset(buffer, 0, sizeof(buffer));}// 6. 關(guān)閉連接close(clientSocket);close(serverSocket);return 0;
}
2.2.4 客戶端編寫
客戶端要做的事有這些:
Step 1:創(chuàng)建Socket對(duì)象,指明需要鏈接的服務(wù)器的地址和端號(hào)
Step 2:鏈接建立后,通過輸出流向服務(wù)器發(fā)送請(qǐng)求信息
Step 3:通過輸出流獲取服務(wù)器響應(yīng)的信息
Step 4:關(guān)閉相關(guān)資源
代碼實(shí)現(xiàn):
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>int main() {// 創(chuàng)建客戶端 Socketint clientSocket = socket(AF_INET, SOCK_STREAM, 0);if (clientSocket == -1) {std::cerr << "Error creating socket!" << std::endl;return 1;}// 配置服務(wù)器地址和端口struct sockaddr_in serverAddr;memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(12345); // 端口號(hào)轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序if (inet_pton(AF_INET, "172.16.2.54", &serverAddr.sin_addr) <= 0) {std::cerr << "Invalid address or address family!" << std::endl;return 1;}// 連接到服務(wù)器if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {std::cerr << "Error connecting to server!" << std::endl;close(clientSocket);return 1;}// 獲取客戶端 IP 地址char clientIp[INET_ADDRSTRLEN];if (inet_ntop(AF_INET, &serverAddr.sin_addr, clientIp, INET_ADDRSTRLEN) == nullptr) {std::cerr << "Error converting IP address!" << std::endl;close(clientSocket);return 1;}// 發(fā)送消息到服務(wù)器const char* message = "客戶端:";send(clientSocket, message, strlen(message), 0);send(clientSocket, clientIp, strlen(clientIp), 0);send(clientSocket, " 接入服務(wù)器!", strlen(" 接入服務(wù)器!"), 0);// 關(guān)閉連接close(clientSocket);return 0;
}
2.3 基于UDP
2.3.1 服務(wù)端實(shí)現(xiàn)
服務(wù)端實(shí)現(xiàn)步驟:
Step 1:創(chuàng)建DatagramSocket,指定端口號(hào)
Step 2:創(chuàng)建DatagramPacket
Step 3:接收客戶端發(fā)送的數(shù)據(jù)信息
Step 4:讀取數(shù)據(jù)
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <unistd.h>int main() {/** 接收客戶端發(fā)送的數(shù)據(jù)*/// 1. 創(chuàng)建服務(wù)器端套接字int serverSocket = socket(AF_INET, SOCK_DGRAM, 0);if (serverSocket == -1) {std::cerr << "Error creating socket!" << std::endl;return 1;}// 2. 配置服務(wù)器地址struct sockaddr_in serverAddr;memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = INADDR_ANY; // 使用本地所有可用地址serverAddr.sin_port = htons(12345); // 端口號(hào)轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序// 3. 綁定端口和地址if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {std::cerr << "Error binding socket!" << std::endl;close(serverSocket);return 1;}// 4. 接收客戶端發(fā)送的數(shù)據(jù)struct sockaddr_in clientAddr;socklen_t clientAddrLen = sizeof(clientAddr);char data[1024];memset(data, 0, sizeof(data));std::cout << "**** 服務(wù)器端已經(jīng)啟動(dòng),等待客戶端發(fā)送數(shù)據(jù) ****" << std::endl;ssize_t bytesRead = recvfrom(serverSocket, data, sizeof(data), 0, (struct sockaddr*)&clientAddr, &clientAddrLen);if (bytesRead == -1) {std::cerr << "Error receiving data!" << std::endl;close(serverSocket);return 1;}data[bytesRead] = '\0'; // 添加字符串結(jié)尾標(biāo)志std::cout << "我是服務(wù)器,客戶端說:" << data << std::endl;/** 向客戶端響應(yīng)數(shù)據(jù)*/// 1. 獲取客戶端的地址和端口struct sockaddr_in responseAddr = clientAddr;socklen_t responseAddrLen = sizeof(responseAddr);// 2. 定義響應(yīng)的數(shù)據(jù)const char* responseMsg = "歡迎您!";// 3. 響應(yīng)客戶端ssize_t bytesSent = sendto(serverSocket, responseMsg, strlen(responseMsg), 0, (struct sockaddr*)&responseAddr, responseAddrLen);if (bytesSent == -1) {std::cerr << "Error sending response!" << std::endl;}// 4. 關(guān)閉套接字close(serverSocket);return 0;
}
2.3.2 客戶端實(shí)現(xiàn)
客戶端實(shí)現(xiàn)步驟:
Step 1:定義發(fā)送信息
Step 2:創(chuàng)建DatagramPacket,包含將要發(fā)送的信息
Step 3:創(chuàng)建DatagramSocket
Step 4:發(fā)送數(shù)據(jù)
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <unistd.h>int main() {/** 向服務(wù)器端發(fā)送數(shù)據(jù)*/// 1. 定義服務(wù)器地址和端口號(hào)struct sockaddr_in serverAddr;memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8800); // 端口號(hào)轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序if (inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr) <= 0) {std::cerr << "Invalid address or address family!" << std::endl;return 1;}// 2. 定義要發(fā)送的數(shù)據(jù)const char* data = "用戶名:admin;密碼:123";// 3. 創(chuàng)建 UDP 套接字int clientSocket = socket(AF_INET, SOCK_DGRAM, 0);if (clientSocket == -1) {std::cerr << "Error creating socket!" << std::endl;return 1;}// 4. 發(fā)送數(shù)據(jù)報(bào)到服務(wù)器ssize_t bytesSent = sendto(clientSocket, data, strlen(data), 0, (struct sockaddr*)&serverAddr, sizeof(serverAddr));if (bytesSent == -1) {std::cerr << "Error sending data!" << std::endl;close(clientSocket);return 1;}/** 接收服務(wù)器端響應(yīng)的數(shù)據(jù)*/// 1. 創(chuàng)建用于接收數(shù)據(jù)的緩沖區(qū)char reply[1024];memset(reply, 0, sizeof(reply));// 2. 接收服務(wù)器響應(yīng)的數(shù)據(jù)struct sockaddr_in responseAddr;socklen_t responseAddrLen = sizeof(responseAddr);ssize_t bytesRead = recvfrom(clientSocket, reply, sizeof(reply), 0, (struct sockaddr*)&responseAddr, &responseAddrLen);if (bytesRead == -1) {std::cerr << "Error receiving data!" << std::endl;} else {std::cout << "我是客戶端,服務(wù)器說:" << reply << std::endl;}// 3. 關(guān)閉套接字close(clientSocket);return 0;
}