歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

Linux操作系統下廣播程序制作介紹

TCP/IP網絡的主要原理

在一個IP(Internet Protocol)網絡中,每一台計算機都有一個32位的IP地址。每台計算機的IP地址都是唯一的。WWW是一個范圍十分大,並且不斷增長的IP網絡,所以網絡上的每台計算機都必須有一個唯一的IP地址。IP地址是用.分隔開的4個十進制數,例如16.42.0.9。實際上IP地址可以分為兩部分:一部分是網絡地址,另一部分是主機地址,例如,在16.42.0.9中,16.42是網絡地址,0.9則為主機地址。而主機地址又可以分為子網地址和主機地址。計算機的IP地址很不容易記憶,如果使用一個名字就可以方便得多。如果使用名字,則必須有某一種機制將名字轉化為IP地址。這些名字可以靜態地保存在/etc/hosts文件中,或者Linux系統請求域名服務器(DNS服務器)來轉換名字。如果使用DNS服務器的話,本地的主機則必須知道一個或者多個DNS服務器的IP地址,這些信息保存在/etc/resolv.conf文件中。

當你和其他計算機相連時,系統要使用IP地址和其他計算機交換數據。數據保存在IP數據包中。每一個IP數據包都有一個IP數據頭,其中包括源地址和目的地址,一個數據校驗和以及其他一些有關的信息。IP數據包的大小隨傳輸介質的不同而不同,例如,以太網的數據包要大於PPP的數據包。目的地址的主機在接收數據包後,必須再將數據裝配起來,然後傳送給接收的應用程序。

連接在同一個IP子網上的主機之間可以直接傳送IP數據包,而在不同子網之間的主機卻要使用網關。網關用來在不同的子網之間傳送數據包。

IP協議是一個傳輸層的協議,其他的協議可以利用IP協議來傳輸數據。TCP(Transmission Control Protocol)協議是一個可靠的點到點之間的協議,它使用IP協議來傳送和接收自己的數據包。TCP協議是基於連接的協議。需要通信的兩個應用程序之間將建立起一條虛擬的連接線路,即使其中要經過很多子網、網關和路由器。TCP協議保證在兩個應用程序之間可靠地傳送和接收數據,並且可以保證沒有丟失的或者重復的數據包。當TCP協議使用IP協議傳送它自己的數據包時,IP數據包中的數據就是TCP數據包本身。相互通信的主機中的IP協議層負責傳送和接收IP數據包。每一個IP數據頭中都包括一個字節的協議標識符。當TCP協議請求IP協議層傳送一個IP數據包時,IP數據頭中的協議標識符指明其中的數據包是一個TCP數據包。接收端的IP層則可以使用此協議標識符來決定將接收到的數據包傳送到那一層,在這裡是TCP協議層。

當應用程序使用TCP/IP通信時,它們不僅要指明目標計算機的IP地址,也要指明應用程序使用的端口地址。端口地址可以唯一地表示一個應用程序,標准的網絡應用程序使用標准的端口地址,例如,web服務器使用端口80。你可以在/etc/services中查看已經登記的端口地址。

IP 協議層也可以使用不同的物理介質來傳送IP數據包到其他的IP地址主機。這些介質可以自己添加協議頭。例如以太網協議層、PPP協議層或者SLIP協議層。以太網可以同時連接很多個主機,每一個主機上都有一個以太網的地址。這個地址是唯一的,並且保存在以太網卡中。所以在以太網上傳輸IP數據包時,必須將IP數據包中的IP地址轉換成主機的以太網卡中的物理地址。Linux系統使用地址解決協議( ARP)來把IP地址翻譯成主機以太網卡中的物理地址。希望把IP地址翻譯成硬件地址的主機使用廣播地址向網絡中的所有節點發送一個包括IP地址的ARP請求數據包。擁有此IP地址的目的計算機接收到請求以後,返回一個包括其物理地址的ARP應答。ARP協議不僅僅限於以太網,它還可以用於其他的物理介質,例如FDDI等。那些不能使用ARP的網絡設備可以標記出來,這樣Linux系統就不會試圖使用ARP。系統中也有一個反向的翻譯協議,叫做RARP,用來將主機的物理地址翻譯成IP地址。網關可以使用此協議來代表遠程網絡中的IP地址回應ARP請求。

BSD 套接口

BSD 套接口是最早的網絡通信的實現,它由一個只處理BSD 套接口的管理軟件支持。其下面是INET套接口層,它管理TCP協議和UDP協議的通信末端。UDP(User Datagram Protocol)是無連接的協議,而TCP則是一個可靠的端到端協議。當網絡中傳送一個UDP數據包時,Linux系統不知道也不關心這些UDP數據包是否安全地到達目的節點。TCP數據包是編號的,同時TCP傳輸的兩端都要確認數據包的正確性。IP協議層是用來實現網間協議的,其中的代碼要為上一層數據准備IP數據頭,並且要決定如何把接收到的IP數據包傳送到TCP協議層或者UDP協議層。在IP協議層的下方是支持整個Linux 網絡系統的網絡設備,例如PPP和以太網。網絡設備並不完全等同於物理設備,因為一些網絡設備,例如回饋設備是完全由軟件實現的。和其他那些使用mknod命令創建的Linux系統的標准設備不同,網絡設備只有在軟件檢測到和初始化這些設備時才在系統中出現。當你構建系統內核時,即使系統中有相應的以太網設備驅動程序,你也只能看到/dev/eth0。ARP協議在IP協議層和支持ARP翻譯地址的協議之間。

================================ 網絡應用程序 用戶層 -------------------------------- BSD 核心層 套接口層 LNET 套接口層 /  \ TCP UDP IP PPP SLIP Ethernet ---> ARP ================================

BSD是UNIX系統中通用的網絡接口,它不僅支持各種不同的網絡類型,而且也是一種內部進程之間的通信機制。兩個通信進程都用一個套接口來描述通信鏈路的兩端。套接口可以認為是一種特殊的管道,但和管道不同的是,套接口對於可以容納的數據的大小沒有限制。Linux支持多種類型的套接口,也叫做套接口尋址族,這是因為每種類型的套接口都有自己的尋址方法。

Linux的BSD 套接口支持下面的幾種套接口類型:

1. 流式(stream)

這些套接口提供了可靠的雙向順序數據流連接。它們可以保證數據傳輸中的完整性、正確性和單一性。INET尋址族中的TCP協議支持這種類型的套接口。

數據流套接口是可靠的雙向連接的通信數據流。如果你在套接口中以“ 1, 2”的順序放入兩個數據,它們在另一端也會以“1, 2”的順序到達。它們也可以被認為是無錯誤的傳輸。

經常使用的telnet應用程序就是使用數據流套接口的一個例子。使用HTTP的WWW浏覽器也使用數據流套接口來讀取網頁。事實上,如果你使用telnet 登錄到一個WWW站點的8 0端口,然後鍵入“GET 網頁名”,你將可以得到這個Html頁。數據流套接口使用TCP得到這種高質量的數據傳輸。數據報套接口使用UDP,所以數據報的順序是沒有保障的。數據報是按一種應答的方式進行數據傳輸的。

2. 數據報(Datagram)

這種類型的套接口也可以像流式套接口一樣提供雙向的數據傳輸,但它們不能保證傳輸的數據一定能夠到達目的節點。即使數據能夠到達,也無法保證數據以正確的順序到達以及數據的單一性、正確性。U D P協議支持這種類型的套接口。

3. 原始(Raw)

這種類型的套接口允許進程直接存取下層的協議。

4. 可靠遞送消息(Reliable Delivered Messages)

這種套接口和數據報套接口一樣,只能保證數據的到達。

5. 順序數據包(Sequenced Packets)

這種套接口和流式套接口相同,除了數據包的大小是固定的。

6. 數據包(Packet)

這不是標准的BSD 套接口類型,而是Linux 中的一種擴展。它允許進程直接存取設備層的數據包。




更多的請看:http://www.QQread.com/windows/2003/index.html

基本套接口選項

SO_KEEPALIVE

檢測對方主機是否崩潰,避免(服務器)永遠阻塞於TCP連接的輸入。 設置該選項後,如果2小時內在此套接口的任一方向都沒有數據交換,TCP就自動給對方 發一個保持存活探測分節(keepalive probe)。這是一個對方必須響應的TCP分節.它會導致以下三種情況:

對方接收一切正常:以期望的ACK響應。2小時後,TCP將發出另一個探測分節。

對方已崩潰且已重新啟動:以RST響應。套接口的待處理錯誤被置為ECONNRESET,套接 口本身則被關閉。 對方無任何響應:源自berkeley的TCP發送另外8個探測分節,相隔75秒一個,試圖得到 一個響應。在發出第一個探測分節11分鐘15秒後若仍無響應就放棄。套接口的待處理錯 誤被置為ETIMEOUT,套接口本身則被關閉。如ICMP錯誤是“host unreachable(主機不 可達)”,說明對方主機並沒有崩潰,但是不可達,這種情況下待處理錯誤被置為EHOSTUNREACH。

SO_RCVBUF和SO_SNDBUF 每個套接口都有一個發送緩沖區和一個接收緩沖區。 接收緩沖區被TCP和UDP用來將接收到的數據一直保存到由應用進程來讀。 TCP:TCP通告另一端的窗口大小。 TCP套接口接收緩沖區不可能溢出,因為對方不允許發出超過所通告窗口大小的數據。 這就是TCP的流量控制,如果對方無視窗口大小而發出了超過宙口大小的數據,則接 收方TCP將丟棄它。 UDP:當接收到的數據報裝不進套接口接收緩沖區時,此數據報就被丟棄。UDP是沒有 流量控制的;快的發送者可以很容易地就淹沒慢的接收者,導致接收方的UDP丟棄數據報。

SO_LINGER

指定函數CLOSE對面相連接的協議如何操作——當由數據殘留在套接口發送緩沖區時的處理 LINGER結構

strUCt linger { int l_onoff; // 0=off, nonzero=on int l_linger; //linger time in seconds };

SO_RCVLOWAT 和SO_SNDLOWAT

每個套接口都有一個接收低潮限度和一個發送低潮限度。它們是函數select使用的, 接收低潮限度是讓select返回“可讀”而在套接口接收緩沖區中必須有的數據總量。 ——對於一個TCP或UDP套接口,此值缺省為1。發送低潮限度是讓select返回“可寫” 而在套接口發送緩沖區中必須有的可用空間。對於TCP套接口,此值常缺省為2048。 對於UDP使用低潮限度, 由於其發送緩沖區中可用空間的字節數是從不變化的,只要 UDP套接口發送緩沖區大小大於套接口的低潮限度,這樣的UDP套接口就總是可寫的。 UDP沒有發送緩沖區,只有發送緩沖區的大小

SO_BROADCAST套接口選項

這個選項能夠讓我們使能或者禁止套接口的發送廣播能力。只能在數據報模式下使用廣播,並且還必須是支持廣播消息的以太網等網絡上。如果是點對點的鏈路上就無法辦到這一點。

因為使能廣播的功能必須顯式執行。因此可以避免一些UDP程序無意中把廣播地址當作目的地址進行發送。但是Linux在處理廣播地址的時候,不是由用戶來識別的,在用戶空間所看到的地址格式是沒有差別的。一直到內核才會識別出廣播地址出來,並加以相應的處理。

數據結構

下面我們要討論使用套接口編寫程序可能要用到的數據結構。

首先是套接口描述符。一個套接口描述符只是一個整型的數值: i n t。

第一個數據結構是struct sockaddr,這個數據結構中保存著套接口的地址信息。

struct sockaddr { unsigned short sa_family; /* address family, AF_xxx */ char sa_data[14]; /* 14 bytes of protocol address */ } ;

sa_family 中可以是其他的很多值,但在這裡我們把它賦值為“ AF_INET”。sa_data包括一個目的地址和一個端口地址。

你也可以使用另一個數據結構sockaddr_in,如下所示:

struct sockaddr_in { short int sin_family; /* Address family */ unsigned short int sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ unsigned char sin_zero[8]; /* Same size as struct sockaddr */ } ;

這個數據結構使得使用其中的各個元素更為方便。要注意的是sin_zero應該使用bzero() 或者memset ( )而設置為全0。另外,一個指向sockaddr_in數據結構的指針可以投射到一個指向數據結構sockaddr的指針,反之亦然。 IP地址和如何使用IP地址



有一系列的程序可以使你處理I P地址。

首先,你可以使用inet_addr( )程序把諸如“ 132.241.5.10“形式的I P地址轉化為無符號的整型數。

ina.sin_addrs_addr = inet_addr("132.241.5.10");

如果出錯,inet_addr( )程序將返回- 1。

也可以調用inet_ntoa( )把地址轉換成數字和句點的形式:

printf( " % s " , inet_ntoa( ina.sin_addr ) ) ;

這將會打印出I P地址。它返回的是一個指向字符串的指針。

socket()

我們使用系統調用socket()來獲得文件描述符:

#include #include int socket(int domain, int type, int protocol);

第一個參數domain設置為“AF_INET”。

第二個參數是套接口的類型:SOCK_DGRAM。

第三個參數設置為0。

系統調用socket()只返回一個套接口描述符,如果出錯,則返回- 1。

bind()

一旦你有了一個套接口以後,下一步就是把套接口綁定到本地計算機的某一個端口上。但如果你只想使用connect( )則無此必要。

下面是系統調用bind( )的使用方法:

#include #include int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

第一個參數sockfd 是由socket( )調用返回的套接口文件描述符。

第二個參數my_addr 是指向數據結構sockaddr的指針。數據結構sockaddr中包括了關於你的地址、端口和IP地址的信息。

第三個參數addrlen可以設置成sizeof(struct sockaddr)。下面是一個例子:

#include #include #include #define MYPORT 3490 main ( ) { int sockfd; struct sockaddr_in my_addr; //說明一個sock地址結構 sockfd = socket(AF_INET, SOCK_STREAM, 0); /* 基本的建立UDP socket,最好進行一些檢查 */ my_addr.sin_family = AF_INET; /* 設定協議集,基於internet協議 */ my_addr.sin_port = htons(MYPORT); // 端口號 my_addr. sin_addr.s_addr = inet_addr("132.241.5.10");//將字符串轉換成標准的地址格式 bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */ /* don't forget your error checking for bind(): */ bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)); //綁定監聽進程到該socket上

如果出錯,bind() 也返回- 1。

如果你使用connect()系統調用,那麼你不必知道你使用的端口號。當你調用connect()時,它檢查套接口是否已經綁定,如果沒有,它將會分配一個空閒的端口。

sendto() 和recvfrom()

因為數據報套接口並不連接到遠程的主機上,所以在發送數據包之前,我們必須首先給出目的地址,請看

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

除了兩個參數以外,其他的參數和系統調用s e n d ( )時相同。參數t o是指向包含目的I P地址和端口號的數據結構s o c k a d d r的指針。參數t o l e n可以設置為sizeof(struct sockaddr)。

系統調用sendto( )返回實際發送的字節數,如果出錯則返回- 1。

系統調用recvfrom( )的使用方法也和r e c v ( )的十分近似:

int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);

sockfd: 描述字

buff: 指向輸入緩沖器的指針

nbytes: 讀字節大小

flag: 標志:0

from :對方協議地址

addrlen: 對方協議地址長度

函數返回值: 讀入數據的長度,可以為0.

參數from是指向本地計算機中包含源I P地址和端口號的數據結構sockaddr的指針。參數fromlen設置為sizeof(struct sockaddr)。

系統調用recvfrom ( )返回接收到的字節數,如果出錯則返回- 1。

close() 和shutdown()

你可以使用close( )調用關閉連接的套接口文件描述符:

close(sockfd) ;

這樣就不能再對此套接口做任何的讀寫操作了。

使用系統調用shutdown(),可有更多的控制權。它允許你在某一個方向切斷通信,或者切斷雙方的通信:

int shutdown(int sockfd, int how);



更多的請看:http://www.qqread.com/windows/2003/index.html

  第一個參數是你希望切斷通信的套接口文件描述符。第二個參數h o w值如下:

0—Further receives are disallowed

1—Further sends are disallowed

2—Further sends and receives are disallowed (like close())

shutdown() 如果成功則返回0,如果失敗則返回- 1。

客戶機/服務器模式

在網絡上大部分的通信都是在客戶機/服務器模式下進行的。例如telnet。當你使用telnet連接到遠程主機的端口23時,主機上的一個叫做telnetd的程序就開始運行。它處理所有進入的telnet連接,為你設置登錄提示符等。

應當注意的是客戶機/服務器模式可以使用SOCK_STREAM、SOCK_DGRAM或者任何其他的方式。例如telnet /telnetd、FTP/ftpd和bootp/bootpd。每當你使用ftp時,遠程計算機都在運行一個ftpd為你服務。

一般情況下,一台機器上只有一個服務器程序,它通過使用fork( )來處理多個客戶端程序的請求。最基本的處理方法是:服務器等待連接,使用accept()接受連接,調用fork( )生成一個子進程處理連接。

UDP廣播模式

廣播的用途之一是假定服務器主機在本地子網上,但不知道它的單播IP地址時,對它進行定位,這就是資源發現(resource discovery)。另一用途是當有多個客戶和單個服務器通信時,減少局域網上數據流量。下面是幾個以此為目的使用廣播的因特網應用實例。

★ARP(地址解析協議,address Resolution Protocol。ARP是IPv4的一個基本組成部分,而不是一個用戶應用程序。ARP在本地子網上廣播一個請求:“具有IP地址a.b.c.d的系統請表明自己,並告訴我,你的硬件地址。”

★BOOTP(引導協議,Bootstrap Protocol)。客戶假定有一台服務器主機在本地子網上。它以廣播地址(通常是255.255.255.255,因為這是客戶還不知道自己的IP地址、子網掩碼或子網的受限廣播地址)為目的地址發出自己的引導請求。

★NTP(網絡時間協議,Network Time Protocol)。一種常見的情形是:一個NTP客戶主機可能配置程使用一個或多個服務器主機的IP地址,其上面的NTP客戶於是以某個頻率(每64秒一次或更長)輪詢這些服務器。客戶采用基於服務器返送的時刻和到達服務器的往返時間的精確算法更新時鐘。但在支持廣播的局域網上,就不需要采用客戶輪詢服務器的方法,而代之以服務器以每64秒一次的頻率向本地子網上的所有客戶廣播當前時刻。這樣便可以減少網絡上的數據流量。

★路由後台進程。routed是最常用的後台進程。它輸出自己的路由表的方法便是局域網廣播。所有其他連接到這些局域網上的路由器便可以同時接收這些路由通告,而不用每個路由器都必須配置其鄰居路由器的IP地址。這個特性也被局域網上的主機用於偵聽路由通告並相應更新它的路由表(許多人認為這是一種“誤用”)

如果用{netid,subnetid,hostoid}。({網絡Id,子網Id,主機ID})表示IPv4地址,那麼有四種類型的廣播地址。我們用-1表示所有比特位均為1的字段。

1、子網廣播地址:{netid,subnetid,-1}。這類地址編排指定子網上的所有接口。例如,如果我們對B類地址128.7采用8位子網ID,那麼128.7.6.225將是128.7.6的子網上所有接口的子網廣播地址。

路由器通常不轉發這類廣播(TCPv2)圖18.2給出了一個連接到128.7.1和128.7.6兩個子網的路由器。路由器在12.7..1子網上接收到一個目的地址為210.37.6.255(另一個接口的子網廣播地址)的單播IP數據報。路由器通常不向128.7.6子網轉發這個數據報。有些系統具有運行轉發子網廣播數據報的配置選項。

2、 全部子網廣播地址:{netid,-1,-1}。這類廣播地址編排指定網絡上的所有子網。如果說這類地址層被用過的話,那麼現在已很少見了。

3、 網絡廣播地址:{netid,-1}。這類地址用於不進行子網劃分的網絡。但不進行子網劃分的網絡現在幾乎不存在了。

4、 受限廣播地址:{-1,-1,-1}或255.255.255.255。路由器從不轉發目的地址為255.255.255.255的IP數據報。

在這四類廣播地址中,子網廣播地址是今天最常見的。但有些老系統仍然發送目的地址為255.255.255.255的數據報。還有些老系統不理解子網廣播地址,他們將僅發往255.255.255.255的數據報解釋為廣播。



在查看廣播之前,我們應該已清楚向單播地址發送UDP數據報的步驟。圖中網絡的地址為192.168.0,其中8位用作子網ID,8位用作主機ID。左邊主機的應用程序在一個UDP套接口上調用sendto函數,將數據報發往IP地址192.168.0.3、端口1234。UDP層附加一個UDP頭部,並將UDP數據報傳遞到IP層。IP層給它附加一個IPv4頭部,並確定其外出接口。在以太網的情況下,將調用ARP來確定與目的IP地址相應的以太網地址:08:00:22:03:ff:42。然後,將分組作為以太網幀發送出去。以太網幀的目的地址是上述48位地址。幀類型字段的值為0800,指示這是一個IPv4分組。IPv6幀類型字段的值為86dd。

中間主機的以太網接口看到該幀,並將它的目的以太網地址與自己的以太網地址(02:60:8c:2f:4e:13:)進行比較。由於二者不相等,接口便忽略該幀。因此,單播幀不會對這台主機造成任何額外開銷。右邊主機的以太網接口也看到該幀。當它將該幀的目的以太網地址與自己的以太網地址進行比較時,發現二者相等,接口便讀入整個幀。由於幀類型字段只為0800,於是將分組放入IP輸入隊列。

當IP層處理該分組時,它首先將目的IP地址進行比較,由於目的地址是其中之一,於是就接受這個分組。

然後,IP層檢查IPv4頭部協議字段,其值對於UDP為17.於是將IP數據報傳送到UDP層。

UDP層檢查其目的端口(如果其UDP套接口已連接,也可能檢查源端口),將數據報方到相應套接口的接收隊列。如果需要,就喚醒進程,由進程讀取這個新接收的數據報。

這個例子的關鍵點是單播IP數據報只能由目的IP地址指定的主機接收。子網上的其它主機不受任何影響。我們現在考慮一個類似的例子:同樣的子網,但發送進程發送的是子網廣播數據報,其地址為192.168.0.255。

當左側的主機發送數據報時,它注意到目的IP地址是子網廣播地址,於是便將它映射程48位的以太網地址ff.ff.ff.ff.ff.ff。這使得子網上的每一個以太網接口都會接收該幀。在圖中右側兩台運行IPv4的主機都接收該幀。由於以太網幀類型是0800,兩個主機都將數據報傳遞到IP層。由於目的IP地址匹配二者的廣播地址,並且協議字段為17(UDP),兩個主機於是都將分組上傳至UDP。

最右邊的主機將UDP數據報傳遞給綁定端口1234的應用進程。接收廣播UDP數據報的應用進程不需要任何特殊的處理,它僅僅創建一個UDP套接口,並將應用的端口號捆綁到其上。(我們假設捆綁的IP地址為INADDR_ANY,這是典型的情況)但是中間的主機沒有任何應用進程綁定UDP端口1234。於是主機的UDP代碼丟棄這個已收到的數據報。這台主機禁止發送端口不可達的ICMP消息,因為這樣做會產生廣播風暴(broadcast storm):子網上許多主機機會同時產生響應,這將導致網絡在幾秒鐘內不可用。在圖中,我們也表示出了左邊主機將輸出數據報又遞送給自己的情況,這是一種廣播屬性:根據定義,廣播要到達子網上的所有主機,包括發送者自身。

我們還假定發送應用進程已經綁定要發送到的端口(1234),因此它將收到它發送的每個數據報的拷貝。(但是一般情況下,沒有將進程捆綁數據報所發送到UDP端口的要求。)

本例也表明了廣播存在地根本問題:子網上所有未參與廣播應用系統的主機也必須完成對數據報的協議處理,直至在UDP層將它丟棄。所有非IP主機(例如與行 Novell IPX 的主機)也必須在鏈路層接收完整的幀,並在該層將它丟棄(假定這些主機不支持幀的幀類型,IPv4分組的幀類型域值為0800)。因此,以高速率產生的IP數據報的應用系統(例如音頻、視頻應用系統)會嚴重影響子網上其他主機的運行。



最右邊的主機將UDP數據報傳遞給綁定端口1234的應用進程。接收廣播UDP數據報的應用進程不需要任何特殊的處理,它僅僅創建一個UDP套接口,並將應用的端口號捆綁到其上。(我們假設捆綁的IP地址為INADDR_ANY,這是典型的情況)但是中間的主機沒有任何應用進程綁定UDP端口1234。於是主機的UDP代碼丟棄這個已收到的數據報。這台主機禁止發送端口不可達的ICMP消息,因為這樣做會產生廣播風暴(broadcast storm):子網上許多主機機會同時產生響應,這將導致網絡在幾秒鐘內不可用。在圖中,我們也表示出了左邊主機將輸出數據報又遞送給自己的情況,這是一種廣播屬性:根據定義,廣播要到達子網上的所有主機,包括發送者自身。

我們還假定發送應用進程已經綁定要發送到的端口(1234),因此它將收到它發送的每個數據報的拷貝。(但是一般情況下,沒有將進程捆綁數據報所發送到UDP端口的要求。)

本例也表明了廣播存在地根本問題:子網上所有未參與廣播應用系統的主機也必須完成對數據報的協議處理,直至在UDP層將它丟棄。所有非IP主機(例如與行 Novell IPX 的主機)也必須在鏈路層接收完整的幀,並在該層將它丟棄(假定這些主機不支持幀的幀類型,IPv4分組的幀類型域值為0800)。因此,以高速率產生的IP數據報的應用系統(例如音頻、視頻應用系統)會嚴重影響子網上其他主機的運行。



Copyright © Linux教程網 All Rights Reserved