㈠ Unity網路編程(一)常見概念
一直用Http用多了 復習一下基礎
Unity通訊一般分為2類
Http : 應用層 Unity內置的UnityWebRequest類進行通信(之前寫過一個分發器垃圾框架)用於交互量比較小
Socket:傳輸層 比較底層 實現TCP/UDP 用於頻繁的通信
這個是基於TCP 和IP傳輸不同消息
這個是三種常見的網路層次劃分
基本數據單位為幀
主要的協議:乙太網協議
基本數據單位為IP數據報;
IP協議(Internet Protocol,網際網路互聯協議)
ICMP協議(Internet Control Message Protocol,網際網路控制報文協議)
ARP協議(Address Resolution Protocol,地址解析協議)
RARP協議(Reverse Address Resolution Protocol,逆地址解析協議)
包含的主要協議:TCP協議(Transmission Control Protocol,傳輸控制協議)、UDP協議(User Datagram Protocol,用戶數據報協議)
數據傳輸基本單位為報文
包含的主要協議:
FTP(文件傳送協議)、Telnet(遠程登錄協議)、DNS(域名解析協議)、SMTP(郵件傳送協議),POP3協議(郵局協議),HTTP協議(Hyper Text Transfer Protocol)。
分配給用戶上網使用的網際協議
目前IPv4多 比如192.168.1.1
新的IPv6(因為IPv4數量不夠分配)如3ffe:3201:1401:1280:c8ff:fe4d:db39:1984。
Internet最基本的協議
TCP負責發現傳輸的問題,一有問題就發出信號,要求重新傳輸,直到所有數據安全正確地傳輸到目的地。
可靠的協議 通過三次握手建立的面向連接通信協議
3次握手 四次揮手 實習生常考
TCP連接建立過程(三次握手):
1.首先Client端發送連接請求報文
2.Server段接受連接後回復ACK報文,並為這次連接分配資源。
3.Client端接收到ACK報文後也向Server段發生ACK報文,並分配資源,這樣TCP連接就建立了。
TCP連接斷開過程(四次揮手):
1.Client端發起中斷連接請求(FIN報文)
2.Server端接到FIN報文後,發送ACK伺服器還有消息沒發完讓Client待命,Client端就進入FIN_WAIT,繼續等待Server端的FIN報文
3.Server端確定數據已發送完成,則向Client端發送FIN報文,
4.Client端收到FIN報文後發送ACK後進入TIME_WAIT狀態,如果Server端沒有收到ACK則可以重傳,Server端收到ACK後 關閉,Client等待了2MSL後依然沒有收到回復客戶端也關閉
SYN:"synchronize"請求同步標志;;ACK:"acknowledge"確認標志";FIN:"Finally"結束標志。
為什麼要三次握手?
防止因為網卡導致Sever收到多次Client請求 建立N個監聽 造成資源浪費
為什麼要四次揮手?
自己不請求直接關閉 但是伺服器還能給你發數據 伺服器浪費資源 而且客戶端也會強行接收
使用TCP的協議:FTP(文件傳輸協議)、Telnet(遠程登錄協議)、SMTP(簡單郵件傳輸協議)、POP3(和SMTP相對,用於接收郵件)、HTTP協議等。
面向無連接的通訊協議
UDP通訊時不需要接收方確認,屬於不可靠的傳輸 會丟包
UDP與TCP位於同一層,但它不管數據包的順序、錯誤或重發
主要用於面向查詢---應答的程序
每個UDP報文分UDP報頭和UDP數據區兩部分
UDP報頭由4個域組成,其中每個域各佔用2個位元組
(1)源埠號;
(2)目標埠號;
(3)數據報長度;
(4)校驗值。
使用UDP協議包括:TFTP(簡單文件傳輸協議)、SNMP(簡單網路管理協議)、DNS(域名解析協議)、NFS、BOOTP。
超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最為廣泛的一種網路協議
HTTP協議特點:
簡單快速 靈活 無連接 無狀態 支持B/S(瀏覽器/伺服器)及C/S(客戶端/伺服器)模式。
URL
和伺服器有一些頻繁的交互 用http時不時請求 叫輪詢 效率低下
soket可以理解為插座 插頭接上了可以保持通信
埠:
每個Socket連接都是從一台計算機網卡的一個埠連接到另外一台計算機網卡的某個埠。
IP是房子的話 埠就是門
TCP埠和UDP埠相互獨立 如TCP255埠 和UDP255埠 不沖突
周知埠
范圍從0到1023,其中80埠分配給WWW服務,21埠分配給FTP服務等。
瀏覽器的地址欄里輸入一個網址的時候是不必指定埠號的,因為在默認情況下WWW服務的埠是「80」。
網路服務是可以使用其他埠號的 比如 網址:8080
但是有些系統協議使用固定的埠號,它是不能被改變的,比如139 埠專門用於NetBIOS與TCP/IP之間的通信,不能手動改變。
自己開發時盡量不要使用1024之下的埠,可能會與系統埠沖突。
服務端:
創建socket對象
bind:綁定IP地址和埠
listen:開始監聽綁定的IP地址和埠,等待客戶端的連接
accept:如果有客戶端發起連接,通過accept接受連接請求,連接成功後會復制一個socket出來用於和當前接受連接的客戶端進行通信。(服務端最初創建的那個socket只是用來監聽並建立連接用的,實際和客戶端通信並不是最初的socket,而是在accept這一步會自動創建一個新的socket出來和客戶端通信。)
read/write:使用新的socket讀寫數據
close:關閉socket,如果關閉的是服務端的監聽socket,則無法接收新的連接,但是已經創建的和客戶端的連接不會被關閉。
客戶端:
創建socket對象
connect:連接服務端,連接成功後系統會自動分配埠
read/write:連接成功後,就可以進行數據的讀寫了,這里讀寫使用的socket還是第一步創建的socket對象。
close:關閉連接。
如果收到了長度為0的數據,則代表遠程socket關閉了連接。
伺服器:
創建socket對象
bind:綁定IP和埠,用於接收數據(注意這里綁定完就可以直接接收數據了,並不需要等待連接)
read/write:讀寫數據
客戶端:
創建socket對象
read/write:讀寫數據,不需要先建立連接,直接給對應的IP+埠發送數據即可。
由於沒有建立連接以及連接的保障,UDP在傳輸效率上會很高
UDP有一個功能是TCP所不具備的,那就是廣播功能(UDP可以將消息發送到在同一廣播網路上的每個主機 CS、魔獸爭霸區域網對戰)。
HTTP/HTTPS(比http更安全):小游戲 網頁 間歇性發送鏈接 偶爾延遲。
TCP長連接: 卡牌游戲 某些mmo 客戶端和伺服器都可以獨立發包 偶爾延遲
UDP:動作游戲 mmo 槍戰 客戶端和伺服器都可以獨立發包 無法接受延遲
可以混合使用你的MMO客戶端也許首先使用HTTP去獲取上一次的更新內容,然後使用UDP跟游戲伺服器進行連接。
現在也有kcp 就是tcp和udp結合 快速安全可靠
簡單直接的長連接
可靠的信息傳輸
數據包的大小沒有限制
坑多 斷線檢測、慢速客戶端響應阻塞數據包,對開放連接的各種dos攻擊,阻塞和非阻塞IO模型
丟包會有阻塞機制(一般是重發 tcp相反) 所以手機游戲ping跳1000就這個原因
只使用一個socket進行通信
快速
基於數據包構建
靈活 多種方式處理延遲
很多東西沒有要自己構建
不可靠
丟包
客戶端直接開始進行計算而不等待服務端確認是一種典型的隱藏延遲的技術(容易被抓包篡改)。
我們到底是使用TCP還是UDP取決於我們能否隱藏延遲。
比如TCP 在棋牌 卡牌游戲 卡1S無所謂 在動作游戲moba游戲就很致命
可靠的UDP/kcp和TCP不一樣,要去實現一個特殊的阻塞控制,而且還要保證可靠性,也可以使用許多支持可靠通信的UDP庫,但是庫一般為了通用會降低某種新能,自己根據項目情況寫可以發揮到極致
如果不知道用什麼就TCP
㈡ 即時通訊軟體開發的網路編程方式有哪些
引言、即時通訊是網上最為流行的通訊方式,市場上也出現了各種各樣的即時通訊軟體。這篇文章將會給大家介紹一些開發即時通訊軟體的網路編程方式。
開發即時通訊軟體需要用到安卓端技術java語言,蘋果端oc語言,電腦端win系統桌面C/C++語言,管理後台資料庫語言,後台管理界面java或者php。建議可以使用第三方SDK,可以有效地避免消息漏發,卡頓,數據並發等很多問題,提高了用戶對產品的體驗感。
三、如何設置編程。
mysql資料庫的用戶名為root,密碼為空,可以根據自己的需要設置相應的用戶名和密碼(固定在程序中)。mychatserver是聊天伺服器,myfileserver是文件伺服器,文件伺服器負責上傳和下載聊天中發送的文件,myimgserver負責上傳和下載聊天中的圖片。三個服務之間相互獨立,不會互相影響。聊天伺服器監聽埠是20000,文件伺服器埠是20001,圖片伺服器埠號是20002,這三個埠的客戶端連接,其中聊天埠和客戶端是長連接,文件埠和圖片可選擇長連接或短連接。第一次運行mychatserver時,如果能順利連上mysql,mychatserver會自動檢測是否存在名為myim的資料庫,如果不存在就可以創建了,並新建三張信息表,分別是用戶信息表,好友關系表和聊天消息記錄表。第一次啟動文件伺服器時會創建filecache目錄,這個目錄用來存儲聊天中的聊天圖片和離線文件以及客戶端的升級包。為了方便查看代碼,可以用Visual Studio管理代碼,使用VS打開myserver.sln查看和管理代碼。
㈢ 網路編程(五)TCP詳解
考慮最簡單的情況:兩台主機之間的通信。這個時候只需要一條網線把兩者連起來,規定好彼此的硬體介面,如都用 USB、電壓 10v、頻率 2.4GHz 等, 這一層就是物理層,這些規定就是物理層協議 。
我們當然不滿足於只有兩台電腦連接,因此我們可以使用交換機把多個電腦連接起來,如下圖:
這樣連接起來的網路,稱為區域網,也可以稱為乙太網(乙太網是區域網的一種)。在這個網路中,我們需要標識每個機器,這樣才可以指定要和哪個機器通信。這個標識就是硬體地址 MAC。
硬體地址隨機器的生產就被確定,永久性唯一。在區域網中,我們需要和另外的機器通信時,只需要知道他的硬體地址,交換機就會把我們的消息發送到對應的機器。
這里我們可以不管底層的網線介面如何發送,把物理層抽離,在他之上創建一個新的層次,這就是 數據鏈路層 。
我們依然不滿足於區域網的規模,需要把所有的區域網聯系起來,這個時候就需要用到路由器來連接兩個區域網:
但是如果我們還是使用硬體地址來作為通信對象的唯一標識,那麼當網路規模越來越大,需要記住所有機器的硬體地址是不現實的;
同時,一個網路對象可能會頻繁更換設備,這個時候硬體地址表維護起來更加復雜。這里使用了一個新的地址來標記一個網路對象: IP 地址 。
通過一個簡單的寄信例子來理解 IP 地址。
我住在北京市,我朋友 A 住在上海市,我要給朋友 A 寫信:
因此,這里 IP 地址就是一個網路接入地址(朋友 A 的住址),我只需要知道目標 IP 地址,路由器就可以把消息給我帶到。 在區域網中,就可以動態維護一個 MAC 地址與 IP 地址的映射關系,根據目的 IP 地址就可以尋找到機器的 MAC 地址進行發送 。
這樣我們不需管理底層如何去選擇機器,我們只需要知道 IP 地址,就可以和我們的目標進行通信。這一層就是 網路層 。網路層的核心作用就是 提供主機之間的邏輯通信 。
這樣,在網路中的所有主機,在邏輯上都連接起來了,上層只需要提供目標 IP 地址和數據,網路層就可以把消息發送到對應的主機。
一個主機有多個進程,進程之間進行不同的網路通信,如邊和朋友開黑邊和女朋友聊微信。我的手機同時和兩個不同機器進行通信。
那麼當我的手機收到數據時,如何區分是微信的數據,還是王者的數據?那麼就必須在網路層之上再添加一層: 運輸層 :
運輸層通過 socket(套接字),將網路信息進行進一步的拆分,不同的應用進程可以獨立進行網路請求,互不幹擾。
這就是運輸層的最本質特點: 提供進程之間的邏輯通信 。這里的進程可以是主機之間,也可以是同個主機,所以在 android 中,socket 通信也是進程通信的一種方式。
現在不同的機器上的應用進程之間可以獨立通信了,那麼我們就可以在計算機網路上開發出形形式式的應用:如 web 網頁的 http,文件傳輸 ftp 等等。這一層稱為 應用層 。
應用層還可以進一步拆分出表示層、會話層,但他們的本質特點都沒有改變: 完成具體的業務需求 。和下面的四層相比,他們並不是必須的,可以歸屬到應用層中。
最後對計網分層進行小結:
這里需要注意的是,分層並不是在物理上的分層,而是邏輯上的分層。通過對底層邏輯的封裝,使得上層的開發可以直接依賴底層的功能而無需理會具體的實現,簡便了開發。
這種分層的思路,也就是責任鏈設計模式,通過層層封裝,把不同的職責獨立起來,更加方便開發、維護等等。
TCP 並不是把應用層傳輸過來的數據直接加上首部然後發送給目標,而是把數據看成一個位元組 流,給他們標上序號之後分部分發送。這就是 TCP 的 面向位元組流 特性:
面向位元組流的好處是無需一次存儲過大的數據佔用太多內存,壞處是無法知道這些位元組代表的意義,例如應用層發送一個音頻文件和一個文本文件,對於 TCP 來說就是一串位元組流,沒有意義可言,這會導致粘包以及拆包問題,後面講。
前面講到,TCP 是可靠傳輸協議,也就是,一個數據交給他,他肯定可以完整無誤地發送到目標地址,除非網路炸了。他實現的網路模型如下:
對於應用層來說,他就是一個可靠傳輸的底層支持服務;而運輸層底層採用了網路層的不可靠傳輸。雖然在網路層甚至數據鏈路層就可以使用協議來保證數據傳輸的可靠性,但這樣網路的設計會更加復雜、效率會隨之降低。把數據傳輸的可靠性保證放在運輸層,會更加合適。
可靠傳輸原理的重點總結一下有: 滑動窗口、超時重傳、累積確認、選擇確認、連續 ARQ 。
停止等待協議
要實現可靠傳輸,最簡便的方法就是:我發送一個數據包給你,然後你跟我回復收到,我繼續發送下一個數據包。傳輸模型如下:
這種「一來一去」的方法來保證傳輸可靠就是 停止等待協議 (stop-and-wait)。不知道還記不記得前面 TCP 首部有一個 ack 欄位,當他設置為 1 的時候,表示這個報文是一個確認收到報文。
然後再來考慮另一種情況:丟包。網路環境不可靠,導致每一次發送的數據包可能會丟失,如果機器 A 發送了數據包丟失了,那麼機器 B 永遠接收不到數據,機器 A 永遠在等待。
解決這個問題的方法是: 超時重傳 。當機器 A 發出一個數據包時便開始計時,時間到還沒收到確認回復,就可以認為是發生了丟包,便再次發送,也就是重傳。
但重傳會導致另一種問題:如果原先的數據包並沒有丟失,只是在網路中待的時間比較久,這個時候機器 B 會受到兩個數據包,那麼機器 B 是如何辨別這兩個數據包是屬於同一份數據還是不同的數據?
這就需要前面講過的方法: 給數據位元組進行編號 。這樣接收方就可以根據數據的位元組編號,得出這些數據是接下來的數據,還是重傳的數據。
在 TCP 首部有兩個欄位:序號和確認號,他們表示發送方數據第一個位元組的編號,和接收方期待的下一份數據的第一個位元組的編號。
停止等待協議的優點是簡單,但缺點是 信道利用率 太低。
假定AB之間有一條直通的信道來傳送分組
這里的TD是A發送分組所需要的時間(顯然TD = 分組長度 / 數據速率)再假定TA是B發送確認分組所需要的時間(A和B處理分組的時間都忽略不計)那麼A在經過TD+RTT+TA時間後才能發送下一個分組,這里的RTT是往返時間,因為只有TD是採用來傳輸有用的數據(這個數據包括了分組首部,如果可以知道傳輸更精確的數據的時間,可以計算的更精確),所有信道利用率為
為了提高傳輸效率,發送方可以不使用低效率的停止等待協議,而是採用 流水線傳輸 :就是發送方可以 連續的發送多個分組 ,不必每發完一個分組就停下來等待對方的確認。這樣可使信道上一直有數據不間斷地在傳送。顯然這種傳輸方式可以獲得很高的信道利用率
停止等待協議已經可以滿足可靠傳輸了,但有一個致命缺點: 效率太低 。發送方發送一個數據包之後便進入等待,這個期間並沒有干任何事,浪費了資源。解決的方法是: 連續發送數據包 。
也就是下面介紹的 連續ARQ協議 和 滑動窗口協議
連續 ARQ 協議
模型如下:
和停止等待最大的不同就是,他會源源不斷地發送,接收方源源不斷收到數據之後,逐一進行確認回復。這樣便極大地提高了效率。但同樣,帶來了一些額外的問題:
發送是否可以無限發送直到把緩沖區所有數據發送完?不可以。因為需要考慮接收方緩沖區以及讀取數據的能力。如果發送太快導致接收方無法接受,那麼只是會頻繁進行重傳,浪費了網路資源。所以發送方發送數據的范圍,需要考慮到接收方緩沖區的情況。這就是 TCP 的 流量控制 。
解決方法是: 滑動窗口 。基本模型如下:
在 TCP 的首部有一個窗口大小欄位,他表示接收方的剩餘緩沖區大小,讓發送方可以調整自己的發送窗口大小。通過滑動窗口,就可以實現 TCP 的流量控制,不至於發送太快,導致太多的數據丟失。
連續 ARQ 帶來的第二個問題是:網路中充斥著和發送數據包一樣數據量的確認回復報文,因為每一個發送數據包,必須得有一個確認回復。提高網路效率的方法是: 累積確認 。
接收方不需要逐個進行回復,而是累積到一定量的數據包之後,告訴發送方,在此數據包之前的數據全都收到。例如,收到 1234,接收方只需要告訴發送方我收到 4 了,那麼發送方就知道 1234 都收到了。
第三個問題是:如何處理丟包情況。在停止等待協議中很簡單,直接一個超時重傳就解決了。但,連續 ARQ 中不太一樣。
例如:接收方收到了 123 567,六個位元組,編號為 4 的位元組丟失了。按照累積確認的思路,只能發送 3 的確認回復,567 都必須丟掉,因為發送方會進行重傳。這就是 GBN(go-back-n) 思路。
但是我們會發現,只需要重傳 4 即可,這樣不是很浪費資源,所以就有了: 選擇確認 SACK 。在 TCP 報文的選項欄位,可以設置已經收到的報文段,每一個報文段需要兩個邊界來進行確定。這樣發送方,就可以根據這個選項欄位只重傳丟失的數據了。
第四個問題是:擁塞控制的問題
也是通過窗口的大小來控制的,但是檢測網路滿不滿是個挺難的事情,所以 TCP 發送包經常被比喻成往誰管理灌水,所以擁塞控制就是在不堵塞,不丟包的情況下盡可能的發揮帶寬。
水管有粗細,網路有帶寬,即每秒鍾能發送多少數據;水管有長度,端到端有時延。理想狀態下,水管裡面的水 = 水管粗細 * 水管長度。對於網路上,通道的容量 = 帶寬 * 往返時延。
如果我們設置發送窗口,使得發送但未確認的包為通道的容量,就能撐滿整個管道。
如圖所示,假設往返時間為 8 秒,去 4 秒,回 4 秒,每秒發送一個包,已經過去了 8 秒,則 8 個包都發出去了,其中前四個已經到達接收端,但是 ACK 還沒返回,不能算發送成功,5-8 後四個包還在路上,還沒被接收,這個時候,管道正好撐滿,在發送端,已發送未確認的 8 個包,正好等於帶寬,也即每秒發送一個包,也即每秒發送一個包,乘以來回時間 8 秒。
如果在這個基礎上調大窗口,使得單位時間可以發送更多的包,那麼會出現接收端處理不過來,多出來的包會被丟棄,這個時候,我們可以增加一個緩存,但是緩存裡面的包 4 秒內肯定達不到接收端課,它的缺點會增加時延,如果時延達到一定程度就會超時重傳
TCP 擁塞控制主要來避免兩種現象,包丟失和超時重傳,一旦出現了這些現象說明發送的太快了,要慢一點。
具體的方法就是發送端慢啟動,比如倒水,剛開始倒的很慢,漸漸變快。然後設置一個閾值,當超過這個值的時候就要慢下來
慢下來還是在增長,這時候就可能水滿則溢,出現擁塞,需要降低倒水的速度,等水慢慢滲下去。
擁塞的一種表現是丟包,需要超時重傳,這個時候,採用快速重傳演算法,將當前速度變為一半。所以速度還是在比較高的值,也沒有一夜回到解放前。
到這里關於 TCP 的可靠傳輸原理就已經介紹得差不多。最後進行一個小結:
當然,這只是可靠傳輸的冰山一角,感興趣可以再深入去研究
㈣ 在java網路編程中,客戶端/伺服器怎麼實現不同電腦之間的通信
1、首先兩台電腦和伺服器都在同一個網路中
2、相互之間可以用sokect<--->server
相互進行通信
㈤ Python網路編程 -- TCP/IP
首先放出一個 TCP/IP 的程序,這里是單線程伺服器與客戶端,在多線程一節會放上多線程的TCP/IP服務程序。
這里將服務端和客戶端放到同一個程序當中,方便對比服務端與客戶端的不同。
TCP/IP是網際網路的通信協議,其參考OSI模型,也採用了分層的方式,對每一層制定了相應的標准。
網際協議(IP)是為全世界通過互聯網連接的計算機賦予統一地址系統的機制,它使得數據包能夠從互聯網的一端發送至另一端,如 130.207.244.244,為了便於記憶,常用主機名代替IP地址,例如 .com。
UDP (User Datagram Protocol,用戶數據報協議) 解決了上述第一個問題,通過埠號來實現了多路復用(用不同的埠區分不同的應用程序)但是使用UDP協議的網路程序需要自己處理丟包、重包和包的亂序問題。
TCP (Transmission Control Protocol,傳輸控制協議) 解決了上述兩個問題,同樣使用埠號實現了復用。
TCP 實現可靠連接的方法:
socket通信模型及 TCP 通信過程如下兩張圖。
[圖片上傳失敗...(image-6d947d-1610703914730)]
[圖片上傳失敗...(image-30b472-1610703914730)]
socket.getaddrinfo(host, port, family, socktype, proto, flags)
返回: [(family, socktype, proto, cannonname, sockaddr), ] 由元組組成的列表。
family:表示socket使用的協議簇, AF_UNIX : 1, AF_INET: 2, AF_INET6 : 10。 0 表示不指定。
socktype: socket 的類型, SOCK_STREAM : 1, SOCK_DGRAM : 2, SOCK_RAW : 3
proto: 協議, 套接字所用的協議,如果不指定, 則為 0。 IPPROTO_TCP : 6, IPPRTOTO_UDP : 17
flags:標記,限制返回內容。 AI_ADDRCONFIG 把計算機無法連接的所有地址都過濾掉(如果一個機構既有IPv4,又有IPv6,而主機只有IPv4,則會把 IPv6過濾掉)
AI _V4MAPPED, 如果本機只有IPv6,服務卻只有IPv4,這個標記會將 IPv4地址重新編碼為可實際使用的IPv6地址。
AI_CANONNAME,返回規范主機名:cannonname。
getaddrinfo(None, 'smtp', 0, socket.SOCK_STREAM, 0, socket.AP_PASSIVE)
getaddrinfo('ftp.kernel.org', 'ftp', 0, 'socket.SOCK_STREAM, 0, socket.AI_ADDRCONFIG | socket.AI_V4MAPPED)
利用已經通信的套接字名提供給getaddrinfo
mysock = server_sock.accept()
addr, port = mysock.getpeername()
getaddrinfo(addr, port, mysock.family, mysock.type, mysock.proto, socket.AI_CANONNAME)
TCP 數據發送模式:
由於 TCP 是發送流式數據,並且會自動分割發送的數據包,而且在 recv 的時候會阻塞進程,直到接收到數據為止,因此會出現死鎖現象,及通信雙方都在等待接收數據導致無法響應,或者都在發送數據導致緩存區溢出。所以就有了封幀(framing)的問題,即如何分割消息,使得接收方能夠識別消息的開始與結束。
關於封幀,需要考慮的問題是, 接收方何時最終停止調用recv才是安全的?整個消息或數據何時才能完整無缺的傳達?何時才能將接收到的消息作為一個整體來解析或處理。
適用UDP的場景:
由於TCP每次連接與斷開都需要有三次握手,若有大量連接,則會產生大量的開銷,在客戶端與伺服器之間不存在長時間連接的情況下,適用UDP更為合適,尤其是客戶端太多的時候。
第二種情況: 當丟包現象發生時,如果應用程序有比簡單地重傳數據聰明得多的方法的話,那麼就不適用TCP了。例如,如果正在進行音頻通話,如果有1s的數據由於丟包而丟失了,那麼只是簡單地不斷重新發送這1s的數據直至其成功傳達是無濟於事的。反之,客戶端應該從傳達的數據包中任意選擇一些組合成一段音頻(為了解決這一問題,一個智能的音頻協議會用前一段音頻的高度壓縮版本作為數據包的開始部分,同樣將其後繼音頻壓縮,作為數據包的結束部分),然後繼續進行後續操作,就好像沒有發生丟包一樣。如果使用TCP,那麼這是不可能的,因為TCP會固執地重傳丟失的信息,即使這些信息早已過時無用也不例外。UDP數據報通常是互聯網實時多媒體流的基礎。
參考資料:
㈥ JavaSocket網路編程怎麼實現不在同一個網路下通訊
如果你需要直接通訊,那麼這是網管的事。不通的網路是沒有辦法的。
不過如果大家都接了互聯網,那麼可以通過中間伺服器轉發的方式進行通訊。伺服器C在公網。那麼客戶端a連接C,客戶端b也連接C,就可以實現轉發。現在大規模的通訊基本都是這個方式。
㈦ java網路編程應該怎樣在客戶端和伺服器間實現通信
以前寫的,照貼了。。。伺服器端:import java.awt.*;x0dx0aimport java.awt.event.WindowAdapter;x0dx0aimport java.awt.event.WindowEvent;x0dx0aimport java.io.*;x0dx0aimport java.net.*;/*6、 採用UDP協議,編寫一個Java網路應用程序,該應用分伺服器端程序和客戶端程序兩部分。x0dx0a* 客戶端指定一個伺服器上的文件名,讓伺服器發回該文件的內容,或者提示文件不存在。x0dx0a* (20分)(服務端程序和客戶端程序分別命名為Server.java和Client.java)*/x0dx0apublic class N4BT6 extends Framex0dx0a{x0dx0aDatagramSocket socket ;x0dx0aDatagramPacket packet ;byte[] buf ;x0dx0aFile file ;x0dx0aFileInputStream input;x0dx0aString message = "該文件不存在";x0dx0aTextArea text;x0dx0apublic N4BT6(String title)x0dx0a{x0dx0asuper(title);x0dx0atext = new TextArea(6,4);x0dx0aadd(text);x0dx0asetSize(400, 300);x0dx0asetVisible(true);x0dx0aaddWindowListener(new WindowAdapter()x0dx0a{x0dx0apublic void windowClosing(WindowEvent e)x0dx0a{x0dx0adispose();x0dx0a}x0dx0a});x0dx0ax0dx0abuf = new byte[1024];x0dx0atryx0dx0a{x0dx0asocket = new DatagramSocket(1230);x0dx0apacket = new DatagramPacket(buf, buf.length);x0dx0asocket.receive(packet);x0dx0afile = new File(new String(packet.getData()));x0dx0asocket = new DatagramSocket();x0dx0a} x0dx0acatch (Exception e)x0dx0a{e.printStackTrace();x0dx0a}x0dx0ax0dx0aif(file.exists())x0dx0a{x0dx0atryx0dx0a{x0dx0abuf = new byte[(int)file.length()];x0dx0apacket = new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),1234);x0dx0ainput = new FileInputStream(file);x0dx0ainput.read(buf);x0dx0asocket.send(packet);x0dx0a}x0dx0acatch (IOException e) x0dx0a{x0dx0ae.printStackTrace();x0dx0a}x0dx0a}x0dx0aelsex0dx0a{x0dx0atryx0dx0a{x0dx0apacket = new DatagramPacket(message.getBytes(),message.getBytes().length,x0dx0aInetAddress.getLocalHost(),1234);x0dx0asocket.send(packet);x0dx0a}x0dx0acatch (Exception e) x0dx0a{x0dx0ae.printStackTrace();x0dx0a}x0dx0a}x0dx0ax0dx0a}x0dx0apublic static void main(String[] args)x0dx0a{x0dx0anew N4BT6("Server");x0dx0a}x0dx0a}x0dx0a客戶端:import java.awt.*;x0dx0aimport java.awt.event.*;x0dx0aimport java.net.DatagramPacket;x0dx0aimport java.net.DatagramSocket;x0dx0aimport java.net.InetAddress;public class N4BT6_2 extends Framex0dx0a{x0dx0aTextArea text;x0dx0aString message = "Q.txt";x0dx0aDatagramSocket socket ;x0dx0aDatagramPacket packet;x0dx0abyte[] buf;x0dx0apublic N4BT6_2(String title)x0dx0a{x0dx0asuper(title);x0dx0atext = new TextArea(6,4);x0dx0aadd(text);x0dx0asetSize(400, 300);x0dx0asetVisible(true);x0dx0aaddWindowListener(new WindowAdapter()x0dx0a{x0dx0apublic void windowClosing(WindowEvent e)x0dx0a{x0dx0adispose();x0dx0a}x0dx0a});x0dx0atryx0dx0a{x0dx0ax0dx0asocket = new DatagramSocket();x0dx0apacket = new DatagramPacket(message.getBytes(),message.getBytes().length,x0dx0aInetAddress.getLocalHost(),1230);x0dx0asocket.send(packet);x0dx0a}x0dx0acatch (Exception e) x0dx0a{x0dx0ae.printStackTrace();x0dx0a}x0dx0ax0dx0atryx0dx0a{x0dx0abuf = new byte[1024];x0dx0asocket = new DatagramSocket(1234);x0dx0apacket = new DatagramPacket(buf,buf.length);x0dx0asocket.receive(packet);x0dx0atext.append(new String(buf));x0dx0a}x0dx0acatch (Exception e) x0dx0a{x0dx0ae.printStackTrace();x0dx0a}x0dx0a}x0dx0apublic static void main(String[] args)x0dx0a{x0dx0anew N4BT6_2("Client");x0dx0a}x0dx0a}