自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Socket UDP協議程序代碼

網絡 網絡管理
下文摘要:文章中,我們對UDP協議的socket的編程進行了分析。那么大家可以通過文章中的代碼來進行一下參考。希望對您有用。

在網絡傳輸層,我們除了常用的TCP是進行傳輸的,還有UDP協議也是應用于傳輸作用。那么這里我們主要極少一下socket發(fā)送UDP協議數據的程序。首先,我們應該理解如下概念:UDP是一個簡單的面向數據報的傳輸層協議,我們先站在UDP客戶端的角度來看看如何發(fā)送一個UDP數據報,以及協議棧為發(fā)送一個UDP數據報做了哪些事情。UDP數據報可以在未連接的socket上發(fā)送(使用sendto系統(tǒng)調用,指定目的地址),也可以在已連接的socket上發(fā)送(使用send系統(tǒng)調用,不用指定目的地址),下面我們分兩種情況討論。

下面是一個在未連接的socket上發(fā)送UDP數據的用戶態(tài)程序示例(注:該程序的格式和風格相當不好,只是為臨時測試使用。),該程序目前還只管發(fā)送,不處理接收,關于接收,我們后面再作分析:

#include<sys/types.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include"my_inet.h"
#include<stdio.h>
#include<errno.h>
#include<arpa/inet.h>
#include<unistd.h>
intmain()
{
inti;
structsockaddr_indest;
dest.sin_family=MY_PF_INET;
dest.sin_port=htons(16000);
dest.sin_addr.s_addr=0x013010AC;//目的地址是172.16.48.1(網絡字節(jié)序)
//創(chuàng)建UDP數據報服務的socket。
intfd=socket(MY_PF_INET,SOCK_DGRAM,MY_IPPROTO_UDP);
if(fd<0){
perror("socket:");
return-1;
}
intbwrite=sendto(fd,"abcdefg",7,0,(structsockaddr*)&dest,sizeof(dest));
if(bwrite==-1){
perror("send:");
close(fd);
return-1;
}
printf("sendto:%d\n",bwrite);
close(fd);
return0;
}

創(chuàng)建socket的操作跟RAW協議的差不多,只有極少區(qū)別,內核中表示套接字的結構上的操作集,協議名略有不同而已。我們重點看sendto操作所引發(fā)的內核代碼執(zhí)行。sendto所到達的my_inet模塊的***站是myinet_sendmsg,一般來講,該函數只要調用UDP協議自己的udp_sendmsg即可,但在之前,它還有一樣事情要完成,就是為這個socket執(zhí)行綁定,這個綁定可能跟服務器端的bind系統(tǒng)調用有些區(qū)別。試想,如果我們用這個UDPsocket發(fā)送出去了一個數據報,但沒有記錄下這個UDPsocket,那等對端的回應數據報來的時候,我們就不知道哪個socket要接收這個數據報了。綁定就是記錄這個UDPsocket。#p#

myudp_hash是一個具有128項的哈希數組,每一項都是一個UDPsocket的鏈表,每個UDPsocket以自己的源地址端口號為哈希主鍵插入這個數組。源地址端口可以是用戶自己指定的,也可以是由內核自動分配的。

內核自動分配的源端口號有一個范圍,這個范圍段似乎是由系統(tǒng)的內存大小決定的(具體有待進一步分析),如果內存大(似乎是有高端內存可用),范圍段是32768-61000,否則就是1024-4999。udp_port_rover是一個全局變量,初始值為范圍段的下限,每次新分配端口,記錄下新分配的端口號,下一次再分配時,在前一次的基礎上加1,然后查詢對應的myudp_hash中的項,如果該項的鏈表不為空,則找下一項,直至遍歷整個數組,如果為空,則分配成功。所以,當連續(xù)分配128個端口后(數組中的128項中,鏈表全不為空),這個查詢必然失敗,***遍歷數組完成時,得到的端口號必然是前一次分配的端口號加127,然后,端口號每次加128,再查詢對應的數組項,看該端口號有沒有被使用掉。

這個描述可能有點模糊,簡單總結一下就是:每次分配一個端口號,先在前一次分配值的基礎上以1為步進值遞增,如果對應的哈希數組中的鏈表為空,則肯定沒有被使用過,直接使用。如果遍歷完整個哈希表都沒有空的鏈表,則要查詢鏈表中的每一項,以得到未使用的端口。

用戶自己指定一個端口,則我們到對應的哈希數組中的鏈表查詢,如果已被使用,并且不能重用,則分配端口號失敗。對用戶自己指定的端口,沒有范圍段的限制。這個一般用于服務端,而自動分配端口用于客戶端。

綁定完成后,myinet_sendmsg會調用myudp_sendmsg,它與myraw_sendmsg所執(zhí)行的操作相差并不多。先查詢輸出路由,然后添加協議首部,***發(fā)送數據包。與raw相比,udp要在IP首部前添加一個UDP首部。以下是UDP首部的定義:

structudphdr{
__u16source;//發(fā)送端端口號。
__u16dest;//目的端端口號。
__u16len;//UDP長度。
__u16check;//UDP檢驗和。
};

UDP協議是一個傳輸層協議,與下層的網絡層協議相比,它不僅需要知道數據傳輸的兩端的主機,還需要知道是主機上的哪個進程在進行數據傳輸,端口號其實就是用于標識發(fā)送進程和接收進程的。UDP長度是UDP頭加上UDP數據的長度(不包括IP首部)。UDP檢驗和覆蓋UDP首部和UDP數據。

由于UDP數據報在未連接的socket上進行發(fā)送,所以每次進入myraw_sendmsg,都要進行輸出路由的查詢,以確定源地址和目的地址。但我們知道,路由是有緩存的,所以,并沒有太多的額外開銷。認為在未連接的socket上發(fā)送UDP數據報開銷要大的觀點并不完全正確。

責任編輯:佟健 來源: 互聯網
相關推薦

2010-07-17 00:55:48

PHP Telnet

2013-07-29 14:28:43

JQueryJQuery實現分頁分頁程序代碼

2011-11-09 13:59:27

代碼腐爛

2009-06-03 14:42:21

Eclipse調試調試Java程序

2011-11-03 15:44:10

程序員

2010-06-29 12:42:05

UDP協議Java

2009-10-26 11:04:36

VB.NET UDP協

2009-06-17 14:29:50

java程序代碼

2010-01-22 15:09:11

VB.NET下載程序

2010-07-12 10:15:47

WinSock APIUDP協議

2014-06-13 13:47:31

UDP

2010-03-23 14:12:43

Python開發(fā)Win

2010-01-15 10:48:29

C++程序代碼

2009-08-24 18:06:36

源程序代碼C#讀取XML文件

2010-07-12 15:40:24

2010-07-12 14:41:35

UDP協議

2010-07-06 15:16:34

UDP協議

2010-07-06 15:28:57

UDP協議基礎

2010-07-08 12:58:03

UDP協議

2010-01-15 18:46:08

C++程序代碼
點贊
收藏

51CTO技術棧公眾號