計算機網路 Linux 解析UDP協議

2021-10-04 10:56:56 字數 4476 閱讀 8168

目錄

一.udp概述

1.什麼是udp協議

2.udp協議的特點

3.udp的首部格式

二.udp設計框架

三.udp程式設計demo

四.udp程式設計常用函式

五.udp協議中一些常見的問題

1.udp報文丟失問題

2.udp報文亂序問題

3.udp流量控制問題

udp 是 user datagram protocol 的簡稱, 中文名是使用者資料報協議,是乙個簡單的面向資料報的傳輸層協議,在網路中用於處理資料報,是一種無連線的協議。udp不提供可靠性的傳輸,它只是把應用程式傳給 ip 層的資料報傳送出去,但是並不能保證它們能到達目的地。由於 udp 在傳輸資料報前不用在客戶和伺服器之間建立乙個連線,且沒有超時重發等機制,故而傳輸速度很快。遠地主機的運輸層在收到udp報文後,不需要給出任何確認。雖然udp不提供可靠交付,但在某些情況下udp卻是一種最有效的工作

方式。下面給出部分使用udp協議的各種應用和應用層協議:

udp是無連線的,即傳送資料之前不需要建立連線因此減少了開銷和傳送資料之前的時延。

udp使用盡最大努力交付,即不保證可靠交付,因此主機不需要維持複雜的連線狀表

不進行分組出錯的恢復和重傳。

udp是面向報文的。傳送方的udp對應用程式交下來的報文,在新增首部後就向下交付ip層。udp對應用層交下來的文,既不合併,也不拆分,而是保留這些報文的邊界。這就是說,應用層交給udp多長的報文,udp就照樣傳送,即一次傳送乙個報文,也就是說,udp一次交付乙個完整的報文。

udp沒有擁塞控制,因此網路出現的擁塞不會使源主機的傳送速率降低。

不對資料報的順序進行檢查,不能保證分組的先後順序。

udp支援一對

一、一對多、多對一和多對多的互動通訊。

udp的首部開銷小。

使用者資料報udp有兩個字段:資料字段和首部字段。首部欄位很簡單,只有8個位元組,由四個字段組成,每個欄位的長度都是兩個位元組。各欄位意義如下:

源埠:源埠號。在需要對方回信時選用。不需要時可用全0。

目的埠:目的埠號。這在終點交付報文時必須使用。

長度:udp使用者資料報的長度,其最小值是8(僅有首部)。

檢驗和檢測udp使用者資料報在傳輸中是否有錯。有錯就丟棄。

如果接收方udp發現收到的報文中的目的埠號不正確(即不存在對應於該埠號的應用程序),就丟棄該報文,並由網際控制報文協議icmp傳送「埠不可達」差錯報文給傳送方。請注意,雖然在udp之間的通訊要用到其埠號,但由於udp的通訊是無連線的,因此不需要使用套接字(tcp之間的通訊必須要在兩個套接字之間建立連線)。

客戶端

#include #include #include #include #include #include #include #include int main()

; printf("input:\n");

fgets(buff,128,stdin);

if(strncmp(buff,"end",3)==0)

sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&saddr,sizeof(saddr));

memset(buff,0,128);

int len = sizeof(saddr);

recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);

printf("buff = %s\n",buff);

} close(sockfd);

}

伺服器

#include #include #include #include #include #include #include #include int main()

; int n = recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);

printf("buff(%d)=%s\n",n,buff);

sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));

} close(sockfd);

}

1.sendto函式

#include #include ssize_t sendto(int sockfd, 

const void *buf,

size_t len,

int flags,

const struct sockaddr *dest_addr,

socklen_t addrlen);

返回值:成功:返回傳送成功的資料長度,失敗: -1。 

2.recvfrom()函式

#include #include ssize_t recvfrom(int sockfd, void *buf,

size_t len,

int flags,

struct sockaddr *src_addr,

socklen_t *addrlen);

引數:返回值:成功:返回接收成功的資料長度,失敗: -1。 

3.bind()函式

#include #include int bind(int sockfd,

const struct sockaddr* my_addr,

socklen_t addrlen);

引數:

返回值: 成功:0,失敗: -1。

但是,如果伺服器程式就緒後一開始就要傳送資料給客戶端,那麼伺服器就需要知道客戶端的位址資訊和埠,那麼就不能讓客戶端的位址資訊和埠號由客戶端所在作業系統分配,而是要在客戶端程式指定了。怎麼指定,那就是呼叫用bind()函式。

所謂的報文丟失是指,在udp伺服器客戶端的例子中,如果客戶端傳送的資料丟失,伺服器會一直等待,直到客戶端的合法資料過來。如果伺服器的響應在中間被路由丟棄,則客戶端會一直阻塞,直到伺服器資料過來。

【解決辦法】

int select (int maxfd + 1,

fd_set *readset,

fd_set *writeset,

fd_set *exceptset,

const struct timeval * timeout);

返回值:>0 就緒描述字的正數目,-1 出錯,0 超時。

所謂亂序就是傳送資料的順序和接收資料的順序不一致,例如傳送資料的順序為a、b、c,但是接收到的資料順序卻為:a、c、b。產生這個問題的原因在於,每個資料報走的路由並不一樣,有的路由順暢,有的卻擁塞,這導致每個資料報到達目的地的順序就不一樣了。udp協議並不保證資料報的按序接收。

【解決辦法】

傳送端在傳送資料時加入資料報序號,這樣接收端接收到報文後可以先檢查資料報的序號,並將它們按序排隊,形成有序的資料報。

我們知道,tcp有滑動視窗進行流量控制和擁塞控制,反觀udp因為其特點無法做到。udp接收資料時直接將資料放進緩衝區內,如果使用者沒有及時將緩衝區的內容複製出來放好的話,後面的到來的資料會接著往緩衝區放,當緩衝區滿時,後來的到的資料就會覆蓋先來的資料而造成資料丟失(因為核心使用的udp緩衝區是環形緩衝區)。因此,一旦傳送方在某個時間點爆發性傳送訊息,接收方將因為來不及接收而發生資訊丟失。

【解決辦法】

解決方法一般採用增大udp緩衝區,使得接收方的接收能力大於傳送方的傳送能力。

int n = 220 * 1024; //220kb

setsocketopt(sockfd, sol_socket, so_rcvbuf, &n, sizeof(n));

計算機網路 UDP協議

源埠與目的埠 可與tcp埠重複。udp長度 包括首部長度和資料長度,單位為位元組,注意資料長度可以為0。udp檢驗和 校驗的是udp首部部分和資料部分,該校驗和是可選的,如果全部填0則表示傳送端沒有計算校驗和。udp資料報有12個位元組的偽首部 源ip,目的ip,8bit 0,8位協議,udp長度 ...

計算機網路 TCP與UDP

1.tcp的三次握手過程?為什麼會採用三次握手,若採用二次握手可以嗎?建立連線的過程是利用客戶伺服器模式,假設主機a為客戶端,主機b為伺服器端。1 tcp的三次握手過程 主機a向b傳送連線請求 主機b對收到的主機a的報文段進行確認 主機a再次對主機b的確認進行確認。2 採用三次握手是為了防止失效的連...

計算機網路 UDP的connect

udp的connect udp是無連線的協議,不需要connect可以直接使用sendto sendmsg等攜帶對端資訊的函式對資料進行傳送接收,但是其實udp的socket也是可以進行connect的。在udp中,使用sendto資料傳輸過程分三階段 a.向udp套接字註冊目標ip和埠號 b.傳輸...