網(wǎng)絡(luò)初識(shí)

前言

之前對(duì)于網(wǎng)絡(luò)這塊的知識(shí)一直是零零散散的,這次抽空好好的做個(gè)總結(jié)。

先給出OSI的7層網(wǎng)絡(luò)模型與TCP/IP四層模型以及對(duì)應(yīng)的網(wǎng)絡(luò)協(xié)議

網(wǎng)絡(luò)分層以及對(duì)應(yīng)的協(xié)議.png

先說(shuō)OSI七層網(wǎng)絡(luò)模型:

  • 物理層:主要定義物理設(shè)備標(biāo)準(zhǔn),如網(wǎng)線的接口類(lèi)型、光纖的接口類(lèi)型、各種傳輸介質(zhì)的傳輸速率等。它的主要作用是傳輸比特流(就是由 1、0 轉(zhuǎn)化為電流強(qiáng)弱來(lái)進(jìn)行傳輸,到達(dá)目的地后在轉(zhuǎn)化為1、0,也就是我們常說(shuō)的模數(shù)轉(zhuǎn)換與數(shù)模轉(zhuǎn)換)。這一層的數(shù)據(jù)叫做比特
  • 數(shù)據(jù)鏈路層:主要將從物理層接收的數(shù)據(jù)進(jìn)行 MAC 地址(網(wǎng)卡的地址)的封裝與解封裝。常把這一層的數(shù)據(jù)叫做。在這一層工作的設(shè)備是交換機(jī),數(shù)據(jù)通過(guò)交換機(jī)來(lái)傳輸。
  • 網(wǎng)絡(luò)層:主要將從下層接收到的數(shù)據(jù)進(jìn)行 IP 地址(例 192.168.0.1)的封裝與解封裝。在這一層工作的設(shè)備是路由器,常把這一層的數(shù)據(jù)叫做數(shù)據(jù)包。
  • 傳輸層:定義了一些傳輸數(shù)據(jù)的協(xié)議和端口號(hào)(WWW 端口 80 等),如:TCP(傳輸控制協(xié)議,傳輸效率低,可靠性強(qiáng),用于傳輸可靠性要求高,數(shù)據(jù)量大的數(shù)據(jù)),UDP(用戶數(shù)據(jù)報(bào)協(xié)議,與 TCP 特性恰恰相反,用于傳輸可靠性要求不高,數(shù)據(jù)量小的數(shù)據(jù),如 QQ 聊天數(shù)據(jù)就是通過(guò)這種方式傳輸?shù)模?主要是將從下層接收的數(shù)據(jù)進(jìn)行分段進(jìn)行傳輸,到達(dá)目的地址后在進(jìn)行重組。常常把這一層數(shù)據(jù)叫做
  • 會(huì)話層:通過(guò)傳輸層(端口號(hào):傳輸端口與接收端口)建立數(shù)據(jù)傳輸?shù)耐?。主要在你的系統(tǒng)之間發(fā)起會(huì)話或或者接受會(huì)話請(qǐng)求(設(shè)備之間需要互相認(rèn)識(shí)可以是 IP 也可以是 MAC 或者是主機(jī)名)
  • 表示層:主要是進(jìn)行對(duì)接收的數(shù)據(jù)進(jìn)行解釋、加密與解密、壓縮與解壓縮等(也就是把計(jì)算機(jī)能夠識(shí)別的東西轉(zhuǎn)換成人能夠能識(shí)別的東西(如圖片、聲音等))
  • 應(yīng)用層 主要是一些終端的應(yīng)用,比如說(shuō)FTP(各種文件下載),WEB(IE瀏覽),QQ之類(lèi)的(你就把它理解成我們?cè)陔娔X屏幕上可以看到的東西.就 是終端應(yīng)用)。

再以TCP/IP分層模型來(lái)說(shuō):

  • 數(shù)據(jù)鏈路層(Network Access Layer)在 TCP/IP 參考模型中并沒(méi)有詳細(xì)描述,只是指出主機(jī)必須使用某種協(xié)議與網(wǎng)絡(luò)相連。
  • 網(wǎng)絡(luò)層(Internet Layer)是整個(gè)體系結(jié)構(gòu)的關(guān)鍵部分,其功能是使主機(jī)可以把分組發(fā)往任何網(wǎng)絡(luò),并使分組獨(dú)立地傳向目標(biāo)。這些分組可能經(jīng)由不同的網(wǎng)絡(luò),到達(dá)的順序和發(fā)送的順序也可能不同。高層如果需要順序收發(fā),那么就必須自行處理對(duì)分組的排序?;ヂ?lián)網(wǎng)層使用因特網(wǎng)協(xié)議(IP,Internet Protocol)。
  • 傳輸層(Tramsport Layer)使源端和目的端機(jī)器上的對(duì)等實(shí)體可以進(jìn)行會(huì)話。在這一層定義了兩個(gè)端到端的協(xié)議:傳輸控制協(xié)議(TCP,Transmission Control Protocol)和用戶數(shù)據(jù)報(bào)協(xié)議(UDP,User Datagram Protocol)。TCP 是面向連接的協(xié)議,它提供可靠的報(bào)文傳輸和對(duì)上層應(yīng)用的連接服務(wù)。為此,除了基本的數(shù)據(jù)傳輸外,它還有可靠性保證、流量控制、多路復(fù)用、優(yōu)先權(quán)和安全性控制等功能。UDP 是面向無(wú)連接的不可靠傳輸?shù)膮f(xié)議,主要用于不需要 TCP 的排序和流量控制等功能的應(yīng)用程序。
  • 應(yīng)用層(Application Layer)包含所有的高層協(xié)議,包括:虛擬終端協(xié)議(TELNET,TELecommunications NETwork)、文件傳輸協(xié)議(FTP,F(xiàn)ile Transfer Protocol)、電子郵件傳輸協(xié)議(SMTP,Simple Mail Transfer Protocol)、域名服務(wù)(DNS,Domain Name 13/04/2018 Page 161 of 283 Service)、網(wǎng)上新聞傳輸協(xié)議(NNTP,Net News Transfer Protocol)和超文本傳送協(xié)議(HTTP,HyperText Transfer Protocol)等。

TCP與UDP的區(qū)別
TCP UDP
面向連接 無(wú)連接
可靠,保證順序,不會(huì)丟包 不可靠,不保證順序,會(huì)丟包
需要資源多,效率低,速度慢 需要資源少,效率高,速度快
只支持點(diǎn)對(duì)點(diǎn)通信 支持一對(duì)一、一對(duì)多、多對(duì)一、多對(duì)多的通信模式
是面向字節(jié)流的 UDP是面向報(bào)文的
有擁塞控制機(jī)制 沒(méi)有擁塞控制,適合媒體通信
TCP的報(bào)文格式
TCP報(bào)文結(jié)構(gòu).png
  • 端口號(hào):識(shí)別同一臺(tái)計(jì)算機(jī)里的不同程序進(jìn)程,TCP報(bào)頭中的源端口號(hào)和目的端口號(hào)同IP數(shù)據(jù)報(bào)中的源IP與目的IP唯一確定一條TCP連接。
  • 序號(hào)和確認(rèn)號(hào):TCP可以可靠傳輸?shù)年P(guān)鍵部分。序號(hào)是本報(bào)文發(fā)送數(shù)據(jù)組的第一個(gè)字節(jié)的序號(hào),在TCP傳輸?shù)牧髦忻恳粋€(gè)字節(jié)就是一個(gè)序號(hào)。eg.一個(gè)報(bào)文段的序號(hào)為300,此報(bào)文段數(shù)據(jù)部分共有100字節(jié),則下一個(gè)報(bào)文段的序號(hào)為400。所以序號(hào)確保了TCP傳輸?shù)挠行蛐?/strong>。 確認(rèn)號(hào),即ACK,指明下一個(gè)期待收到的字節(jié)序號(hào),表明該序號(hào)之前的所有數(shù)據(jù)已經(jīng)正確無(wú)誤的收到。確認(rèn)號(hào)只有當(dāng)ACK標(biāo)志為1時(shí)才有效。比如建立連接時(shí),SYN報(bào)文的ACK標(biāo)志位為0。
  • 數(shù)據(jù)偏移/首部長(zhǎng)度:4bits。由于首部可能含有可選項(xiàng)內(nèi)容,因此TCP報(bào)頭的長(zhǎng)度是不確定的,報(bào)頭不包含任何任選字段則長(zhǎng)度為20字節(jié),4位首部長(zhǎng)度字段所能表示的最大值為1111,轉(zhuǎn)化為10進(jìn)制為15,15*32/8 = 60,故報(bào)頭最大長(zhǎng)度為60字節(jié)。首部長(zhǎng)度也叫數(shù)據(jù)偏移,是因?yàn)槭撞块L(zhǎng)度實(shí)際上指示了數(shù)據(jù)區(qū)在報(bào)文段中的起始偏移值。
  • 保留:為將來(lái)定義新的用途保留,現(xiàn)在一般置0。
  • 控制位:URG ACK PSH RST SYN FIN,共6個(gè),每一個(gè)標(biāo)志位表示一個(gè)控制功能。
    1)URG:緊急指針標(biāo)志,為1時(shí)表示緊急指針有效,為0則忽略緊急指針。
    2)ACK:確認(rèn)序號(hào)標(biāo)志,為1時(shí)表示確認(rèn)號(hào)有效,為0表示報(bào)文中不含確認(rèn)信息,忽略確認(rèn)號(hào)字段。
    3)PSH:push標(biāo)志,為1表示是帶有push標(biāo)志的數(shù)據(jù),指示接收方在接收到該報(bào)文段以后,應(yīng)盡快將這個(gè)報(bào)文段交給應(yīng)用程序,而不是在緩沖區(qū)排隊(duì)。
    4)RST:重置連接標(biāo)志,用于重置由于主機(jī)崩潰或其他原因而出現(xiàn)錯(cuò)誤的連接?;蛘哂糜诰芙^非法的報(bào)文段和拒絕連接請(qǐng)求。
    5)SYN:同步序號(hào),用于建立連接過(guò)程,在連接請(qǐng)求中,SYN=1和ACK=0表示該數(shù)據(jù)段沒(méi)有使用捎帶的確認(rèn)域,而連接應(yīng)答捎帶一個(gè)確認(rèn),即SYN=1和ACK=1。
    6)FIN:finish標(biāo)志,用于釋放連接,為1時(shí)表示發(fā)送方已經(jīng)沒(méi)有數(shù)據(jù)發(fā)送了,即關(guān)閉本方數(shù)據(jù)流。
  • 窗口 滑動(dòng)窗口大小,用來(lái)告知發(fā)送端接受端的緩存大小,以此控制發(fā)送端發(fā)送數(shù)據(jù)的速率,從而達(dá)到流量控制。窗口大小時(shí)一個(gè)16bit字段,因而窗口大小最大為65535。
  • 校驗(yàn)和:奇偶校驗(yàn),此校驗(yàn)和是對(duì)整個(gè)的 TCP 報(bào)文段,包括 TCP 頭部和 TCP 數(shù)據(jù),以 16 位字進(jìn)行計(jì)算所得。由發(fā)送端計(jì)算和存儲(chǔ),并由接收端進(jìn)行驗(yàn)證。
  • 緊急指針:只有當(dāng) URG 標(biāo)志置 1 時(shí)緊急指針才有效。緊急指針是一個(gè)正的偏移量,和順序號(hào)字段中的值相加表示緊急數(shù)據(jù)最后一個(gè)字節(jié)的序號(hào)。 TCP 的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式。
  • 選項(xiàng)和填充:最常見(jiàn)的可選字段是最長(zhǎng)報(bào)文大小,又稱為MSS(Maximum Segment Size),每個(gè)連接方通常都在通信的第一個(gè)報(bào)文段(為建立連接而設(shè)置SYN標(biāo)志為1的那個(gè)段)中指明這個(gè)選項(xiàng),它表示本端所能接受的最大報(bào)文段的長(zhǎng)度。選項(xiàng)長(zhǎng)度不一定是32位的整數(shù)倍,所以要加填充位,即在這個(gè)字段中加入額外的零,以保證TCP頭是32的整數(shù)倍。
  • 數(shù)據(jù)部分: TCP 報(bào)文段中的數(shù)據(jù)部分是可選的。在一個(gè)連接建立和一個(gè)連接終止時(shí),雙方交換的報(bào)文段僅有 TCP 首部。如果一方?jīng)]有數(shù)據(jù)要發(fā)送,也使用沒(méi)有任何數(shù)據(jù)的首部來(lái)確認(rèn)收到的數(shù)據(jù)。在處理超時(shí)的許多情況中,也會(huì)發(fā)送不帶任何數(shù)據(jù)的報(bào)文段。

TCP的三次握手與四次揮手過(guò)程,各個(gè)狀態(tài)名稱與含義
三次握手.png
  • 三次握手(我要和你建立鏈接,你真的要和我建立鏈接么,我真的要和你建立鏈接,成功)

第一次握手: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之間可以開(kāi)始傳輸數(shù)據(jù)了。

  • 四次揮手
    這是由于 TCP 的半關(guān)閉造成的。因?yàn)?TCP 連接是全雙工的(即數(shù)據(jù)可在兩個(gè)方向上同時(shí)傳遞)所以進(jìn)行關(guān)閉時(shí)每個(gè)方向上都要單獨(dú)進(jìn)行關(guān)閉。這個(gè)單方向的關(guān)閉就叫半關(guān)閉。當(dāng)一方完成它的數(shù)據(jù)發(fā)送任務(wù),就發(fā)送一個(gè) FIN 來(lái)向另一方通告將要終止這個(gè)方向的連接。
    四次揮手.png

第一次揮手:Client發(fā)送一個(gè)FIN,用來(lái)關(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)。此時(shí)TCP鏈接處于半關(guān)閉狀態(tài),即客戶端已經(jīng)沒(méi)有要發(fā)送的數(shù)據(jù)了,但服務(wù)端若發(fā)送數(shù)據(jù),則客戶端仍要接收。

第三次揮手:Server發(fā)送一個(gè)FIN,用來(lái)關(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),完成四次揮手。

為什么TCP鏈接需要三次握手,兩次不可以么,為什么?

為了防止已失效的鏈接請(qǐng)求報(bào)文突然又傳送到了服務(wù)端,因而產(chǎn)生錯(cuò)誤。

客戶端發(fā)出的連接請(qǐng)求報(bào)文并未丟失,而是在某個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)長(zhǎng)時(shí)間滯留了,以致延誤到鏈接釋放以后的某個(gè)時(shí)間才到達(dá)Server。這是,Server誤以為這是Client發(fā)出的一個(gè)新的鏈接請(qǐng)求,于是就向客戶端發(fā)送確認(rèn)數(shù)據(jù)包,同意建立鏈接。若不采用“三次握手”,那么只要Server發(fā)出確認(rèn)數(shù)據(jù)包,新的鏈接就建立了。由于client此時(shí)并未發(fā)出建立鏈接的請(qǐng)求,所以其不會(huì)理睬Server的確認(rèn),也不與Server通信;而這時(shí)Server一直在等待Client的請(qǐng)求,這樣Server就白白浪費(fèi)了一定的資源。若采用“三次握手”,在這種情況下,由于Server端沒(méi)有收到來(lái)自客戶端的確認(rèn),則就會(huì)知道Client并沒(méi)有要求建立請(qǐng)求,就不會(huì)建立鏈接。

TCP協(xié)議如何來(lái)保證傳輸?shù)目煽啃?/h5>
  • 數(shù)據(jù)包校驗(yàn):目的是檢測(cè)數(shù)據(jù)在傳輸過(guò)程中的任何變化,若校驗(yàn)出包有錯(cuò),則丟棄報(bào)文段并且不給出響應(yīng),這時(shí)TCP發(fā)送數(shù)據(jù)端超時(shí)后會(huì)重發(fā)數(shù)據(jù);
  • 對(duì)失序數(shù)據(jù)包重排序:既然TCP報(bào)文段作為IP數(shù)據(jù)報(bào)來(lái)傳輸,而IP數(shù)據(jù)報(bào)的到達(dá)可能會(huì)失序,因此TCP報(bào)文段的到達(dá)也可能會(huì)失序。TCP將對(duì)失序數(shù)據(jù)進(jìn)行重新排序,然后才交給應(yīng)用層;
  • 丟棄重復(fù)數(shù)據(jù):對(duì)于重復(fù)數(shù)據(jù),能夠丟棄重復(fù)數(shù)據(jù);
  • 應(yīng)答機(jī)制:當(dāng)TCP收到發(fā)自TCP連接另一端的數(shù)據(jù),它將發(fā)送一個(gè)確認(rèn)。這個(gè)確認(rèn)不是立即發(fā)送,通常將推遲幾分之一秒;
  • 超時(shí)重發(fā):當(dāng)TCP發(fā)出一個(gè)段后,它啟動(dòng)一個(gè)定時(shí)器,等待目的端確認(rèn)收到這個(gè)報(bào)文段。如果不能及時(shí)收到一個(gè)確認(rèn),將重發(fā)這個(gè)報(bào)文段;
  • 流量控制:TCP連接的每一方都有固定大小的緩沖空間。TCP的接收端只允許另一端發(fā)送接收端緩沖區(qū)所能接納的數(shù)據(jù),這可以防止較快主機(jī)致使較慢主機(jī)的緩沖區(qū)溢出,這就是流量控制。TCP使用的流量控制協(xié)議是可變大小的滑動(dòng)窗口協(xié)議。
TCP的擁塞處理

從輸入網(wǎng)址到獲得頁(yè)面的過(guò)程

(1). 瀏覽器查詢 DNS,獲取域名對(duì)應(yīng)的IP地址:具體過(guò)程包括瀏覽器搜索自身的DNS緩存、搜索操作系統(tǒng)的DNS緩存、讀取本地的Host文件和向本地DNS服務(wù)器進(jìn)行查詢等。對(duì)于向本地DNS服務(wù)器進(jìn)行查詢,如果要查詢的域名包含在本地配置區(qū)域資源中,則返回解析結(jié)果給客戶機(jī),完成域名解析(此解析具有權(quán)威性);如果要查詢的域名不由本地DNS服務(wù)器區(qū)域解析,但該服務(wù)器已緩存了此網(wǎng)址映射關(guān)系,則調(diào)用這個(gè)IP地址映射,完成域名解析(此解析不具有權(quán)威性)。如果本地域名服務(wù)器并未緩存該網(wǎng)址映射關(guān)系,那么將根據(jù)其設(shè)置發(fā)起遞歸查詢或者迭代查詢;

(2). 瀏覽器獲得域名對(duì)應(yīng)的IP地址以后,瀏覽器向服務(wù)器請(qǐng)求建立鏈接,發(fā)起三次握手;

(3). TCP/IP鏈接建立起來(lái)后,瀏覽器向服務(wù)器發(fā)送HTTP請(qǐng)求;

(4). 服務(wù)器接收到這個(gè)請(qǐng)求,并根據(jù)路徑參數(shù)映射到特定的請(qǐng)求處理器進(jìn)行處理,并將處理結(jié)果及相應(yīng)的視圖返回給瀏覽器;

(5). 瀏覽器解析并渲染視圖,若遇到對(duì)js文件、css文件及圖片等靜態(tài)資源的引用,則重復(fù)上述步驟并向服務(wù)器請(qǐng)求這些資源;

(6). 瀏覽器根據(jù)其請(qǐng)求到的資源、數(shù)據(jù)渲染頁(yè)面,最終向用戶呈現(xiàn)一個(gè)完整的頁(yè)面。

Http怎么處理長(zhǎng)連接

在HTTP1.0和HTTP1.1協(xié)議中都有對(duì)長(zhǎng)連接的支持。其中HTTP1.0需要在request中增加Connection: keep-alive header才能夠支持,而HTTP1.1默認(rèn)支持。

C/S模式下使用socket通信,幾個(gè)關(guān)鍵函數(shù)

編寫(xiě)一個(gè)基于UDP傳輸協(xié)議的網(wǎng)絡(luò)編程:
先構(gòu)建服務(wù)端

package com.suxin.socket.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Mysever {

    /**
     *  1.創(chuàng)建服務(wù)端+端口
     *  2.準(zhǔn)備接受容器
     *  3.封裝成包
     *  4.接收數(shù)據(jù)
     *  5.分析數(shù)據(jù)
     *  6.釋放資源
     *
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        //創(chuàng)建服務(wù)端以及端口
        DatagramSocket server = new DatagramSocket(8899);
        // 構(gòu)造接收器
        byte[] container = new byte[1024];
        // 使用構(gòu)造器打包
        DatagramPacket packet = new DatagramPacket(container,container.length);
        boolean flag = true;
        while(flag) {
            server.receive(packet);//接受數(shù)據(jù)
            byte[] bytes = packet.getData();
            int len = packet.getLength();
            String s = new String(bytes,0,len);
            System.out.println(s);
            if(s.equals("quit server")) {
                flag = false;
            }
        }
        server.close();
    }
}

繼續(xù)構(gòu)建客戶端:

package com.suxin.socket.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.Scanner;

public class Myclient {
    
    public static void main(String[] args) throws IOException {
        //創(chuàng)建服務(wù)端以及端口
        DatagramSocket client = new DatagramSocket(6666);
        //準(zhǔn)備數(shù)據(jù)
        Scanner sc = new Scanner(System.in);
        boolean flag = true;
        while(flag) {
            System.out.println("請(qǐng)輸入傳輸數(shù)據(jù)(以enter結(jié)束):");
            String message = sc.nextLine();
            byte[] b = message.getBytes();
            //打包發(fā)送
            DatagramPacket packet = new DatagramPacket(b,b.length,new InetSocketAddress("127.0.0.1",8899));
            client.send(packet);
            System.out.println("數(shù)據(jù):"+message+"已經(jīng)發(fā)送");
            if(message.equals("close")) {
                flag = false;
            }
        }
        client.close();
    }
}

如果我們關(guān)閉服務(wù)端,運(yùn)行客戶端,依然可以成功。但是此時(shí)并沒(méi)有消息顯示。說(shuō)明即使在服務(wù)端不開(kāi)啟的情況下,基于這種協(xié)議的依然可以執(zhí)行,但是數(shù)據(jù)會(huì)丟失。注意:數(shù)據(jù)傳輸?shù)倪^(guò)程中,必須使用字節(jié)數(shù)組。輸入quit server以后還是可以繼續(xù)發(fā)送消息的。

編寫(xiě)一個(gè)基于TCP協(xié)議的網(wǎng)絡(luò)編程:
服務(wù)端:

package com.suxin.socket.tcp;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8899);

        Socket socket = server.accept();//等待接受外部請(qǐng)求
        System.out.println("客戶端建立連接");
        String message = "歡迎使用";
        
        DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
        dataOutputStream.writeUTF(message);

        dataOutputStream.flush();
    }
}

客戶端:

package com.suxin.socket.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class MyClient {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",8899);
        DataInputStream input=new DataInputStream(socket.getInputStream());
        String echo = input.readUTF();
        System.out.println(echo);
        DataOutputStream output = new DataOutputStream(socket.getOutputStream());
        output.writeUTF("i love u");
        System.out.println("[i love u]數(shù)據(jù)已經(jīng)發(fā)送");
    }
}

以上就是UDP/IP與TCP/IP的基本實(shí)現(xiàn)。但是,我們知道,TCP/Ip的實(shí)現(xiàn)僅僅是實(shí)現(xiàn)了一個(gè)客戶端的連接,這是不符合實(shí)際的,實(shí)際情況下服務(wù)器一般都是有多個(gè)客戶端的連接。這也很好解決,我們只需要在服務(wù)器端加一個(gè)循環(huán),對(duì)于每一次來(lái)自客戶端的請(qǐng)求,服務(wù)器端的Accept()方法都會(huì)返回一個(gè)Socket對(duì)象,這樣就實(shí)現(xiàn)了多個(gè)連接。


參考鏈接
UDP/IP與TCP/IP協(xié)議 帶編程解讀
網(wǎng)絡(luò)相關(guān)的面試題
面試/筆試第一彈 —— 計(jì)算機(jī)網(wǎng)絡(luò)面試問(wèn)題集錦
3分鐘看懂什么是三次握手/四次揮手
java socket編程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容