SYNOPSIS(總覽)
#include <sys/socket.h>
#include <net/netinet.h>程序員
tcp_socket = socket(PF_INET, SOCK_STREAM, 0);
raw_socket = socket(PF_INET, SOCK_RAW, protocol);
udp_socket = socket(PF_INET, SOCK_DGRAM, protocol); 服務器
DESCRIPTION(描述)
Linux 實現描述於 RFC791 和 RFC1122 中的 Internet 協議,版本4. ip 包括遵循 RFC1112 的第二層的多信道廣播技術的實現.它也包括含包過濾器的IP路由器.網絡
程序員的接口與 BSD 的套接字(socket)兼容.要得到關於套接字的更多信息,參見 socket(7) socket
建立一個IP套接字是經過以 socket(PF_INET, socket_type, protocol) 方式調用 socket(2) 函數來實現的.有效的套接字類型(socket_type)有: SOCK_STREAM 用來打開一個 tcp(7) 套接字, SOCK_DGRAM 用來打開一個 udp(7) 套接字,或者是 SOCK_RAW 用來打開一個 raw(7) 套接字用來直接訪問 IP 協議. protocol 指的是要接收或者發送出去的包含在 IP 頭標識(header)中的 IP 協議.對於TCP套接字而言,惟一的有效 protocol 值是 0 和 IPPROTO_TCP 對於UDP套接字而言,惟一的有效 protocol 值是 0 和 IPPROTO_UDP. 而對於 SOCK_RAW 你能夠指定一個在 RFC1700 中定義的有效 IANA IP 協議代碼來賦值. tcp
當一個進程但願接受新的來訪包或者鏈接時,它應該使用 bind(2) 綁定一個套接字到一個本地接口地址.任意給定的本地(地址,端口)對只能綁定一個IP套接字.當調用 bind 時中聲明瞭 INADDR_ANY 時,套接字將會綁定到 全部 本地接口.當在未綁定的套接字上調用 listen(2) 或者 connect(2) 時,套接字會自動綁定到一個本地地址設置爲 INADDR_ANY 的隨機的空閒端口上. 函數
除非你設置了 S0_REUSEADDR 標識,不然一個已綁定的 TCP 本地套接字地址在關閉後的一段時間內不可用.使用該標識的時候要當心,由於它會使 TCP 變得不可靠. 優化
ADDRESS FORMAT(地址格式)
一個 IP 套接字地址定義爲一個 IP 接口地址和一個端口號的組合.基本 IP 協議不會提供端口號,它們經過更高層次的協議如 udp(7) 和 tcp(7) 來實現.對於raw套接字, sin_port 設置爲IP協議.spa
-
-
struct sockaddr_in {
sa_family_t sin_family; /* 地址族: AF_INET */
u_int16_t sin_port; /* 按網絡字節次序的端口 */
struct in_addr sin_addr; /* internet地址 */
};
/* Internet地址. */
struct in_addr {
u_int32_t s_addr; /* 按網絡字節次序的地址 */
};
sin_family 老是設置爲 AF_INET. 這是必需的;在 Linux 2.2 中,若是該設置缺失,大多數聯網函數會返回 EINVAL sin_port 包含按網絡字節排序的端口號.端口號在1024如下的稱爲 保留端口. 只有那些有效用戶標識爲 0 或者 CAP_NET_BIND_SERVICE 有功能的進程才能夠 bind(2) 到這些套接字.注意原始的(raw)IPv4協議沒有這樣的端口概念,它們只經過更高的協議如 tcp(7) 和 udp(7) 來實現.代理
sin_addr 指的是 IP 主機地址. 在 struct in_addr 中的 addr 部分包含按網絡字節序的主機接口地址. in_addr 應該只能經過使用 inet_aton(3), inet_addr(3), inet_makeaddr(3) 庫函數或者直接經過名字解析器(參見 gethostbyname(3)) 來訪問. IPv4 地址分紅單點廣播,廣播傳送和多點廣播地址.單點廣播地址指定了一臺主機的單一接口,廣播地址指定了在一個網段上的全部主機,而多點廣播地址則在一個多點傳送組中尋址全部主機. 只有當設置了套接字標識 SO_BROADCAST 時,才能收發數據報到廣播地址.在當前的實現中,面向鏈接的套接字只容許使用單點傳送地址.指針
注意地址和端口老是按照網絡字節序存儲的.這意味着你須要對分配給端口的號碼調用 htons(3). 全部在標準庫中的地址/端口處理函數都是按網絡字節序運行的.
有幾個特殊的地址: INADDR_LOOPBACK (127.0.0.1) 老是表明經由迴環設備的本地主機; INADDR_ANY (0.0.0.0) 表示任何可綁定的地址; INADDR_BROADCAST (255.255.255.255) 表示任何主機,因爲歷史的緣由,這與綁定爲 INADDR_ANY 有一樣的效果.
SOCKET OPTIONS(套接字選項)
IP 支持一些與協議相關的套接字選項,這些選項能夠經過 setsockopt(2) 設置,並能夠經過 getsockopt(2) 讀取. IP 的套接字選項級別爲 SOL_IP
-
IP_OPTIONS
-
設置或者獲取將由該套接字發送的每一個包的 IP 選項.該參數是一個指向包含選項和選項長度的存儲緩衝區的指針.
setsockopt(2) 系統調用設置與一個套接字相關聯的 IP 選項. IPv4 的最大選項長度爲 40 字節.參閱 RFC791 獲取可用的選項.若是一個
SOCK_STREAM 套接字收到的初始鏈接請求包包含 IP 選項時, IP 選項自動設置爲來自初始包的選項,同時反轉路由頭.在鏈接創建之後將不容許來訪的包修改選項.缺省狀況下是關閉對全部來訪包的源路由選項的,你能夠用
accept_source_route sysctl 來激活.仍然處理其它選項如時間戳(timestamp).對於數據報套接字而言,IP 選項只能由本地用戶設置.調用帶
IP_OPTIONS 的
getsockopt(2) 會把當前用於發送的 IP 選項放到你提供的緩衝區中.
-
IP_PKTINFO
-
傳遞一條包含
pktinfo 結構(該結構提供一些來訪包的相關信息)的
IP_PKTINFO 輔助信息. 這個選項只對數據報類的套接字有效.
-
-
struct in_pktinfo
{
unsigned int ipi_ifindex; /* 接口索引 */
struct in_addr ipi_spec_dst; /* 路由目的地址 */
struct in_addr ipi_addr; /* 頭標識目的地址 */
};
-
ipi_ifindex 指的是接收包的接口的惟一索引.
ipi_spec_dst 指的是路由表記錄中的目的地址,而
ipi_addr 指的是包頭中的目的地址.若是給 sendmsg (2)傳遞了
IP_PKTINFO, 那麼外發的包會經過在
ipi_ifindex 中指定的接口發送出去,同時把
ipi_spec_dst 設置爲目的地址.
-
IP_RECVTOS
-
若是打開了這個選項,則
IP_TOS , 輔助信息會與來訪包一塊兒傳遞.它包含一個字節用來指定包頭中的服務/優先級字段的類型.該字節爲一個布爾整型標識.
-
IP_RECVTTL
-
當設置了該標識時,傳送一條帶有用一個字節表示的接收包生存時間(time to live)字段的
IP_RECVTTL 控制信息.此選項還不支持
SOCK_STREAM 套接字.
-
IP_RECVOPTS
-
用一條
IP_OPTIONS 控制信息傳遞全部來訪的 IP 選項給用戶.路由頭標識和其它選項已經爲本地主機填好.此選項還不支持
SOCK_STREAM 套接字.
-
IP_RETOPTS
-
等同於
IP_RECVOPTS 可是返回的是帶有時間戳的未處理的原始選項和在這段路由中未填入的路由記錄項目.
-
IP_TOS
-
設置或者接收源於該套接字的每一個IP包的 Type-Of-Service (TOS 服務類型)字段.它被用來在網絡上區分包的優先級. TOS 是單字節的字段.定義了一些的標準 TOS 標識:
IPTOS_LOWDELAY 用來爲交互式通訊最小化延遲時間,
IPTOS_THROUGHPUT 用來優化吞吐量,
IPTOS_RELIABILITY 用來做可靠性優化,
IPTOS_MINCOST 應該被用做"填充數據",對於這些數據,低速傳輸是可有可無的.至多隻能聲明這些 TOS 值中的一個.其它的都是無效的,應當被清除.缺省時,Linux首先發送
IPTOS_LOWDELAY 數據報, 可是確切的作法要看配置的排隊規則而定. 一些高優先級的層次可能會要求一個有效的用戶標識 0 或者
CAP_NET_ADMIN 能力. 優先級也能夠以於協議無關的方式經過(
SOL_SOCKET, SO_PRIORITY )套接字選項(參看
socket(7) )來設置.
-
IP_TTL
-
設置或者檢索今後套接字發出的包的當前生存時間字段.
-
IP_HDRINCL
-
若是打開的話, 那麼用戶可在用戶數據前面提供一個 ip 頭. 這隻對
SOCK_RAW 有效.參看
raw(7) 以得到更多信息.當激活了該標識以後,其值由
IP_OPTIONS 設定,而且
IP_TOS 被忽略.
-
IP_RECVERR
-
容許傳遞擴展的可靠的錯誤信息. 若是在數據報上激活了該標識, 那麼全部產生的錯誤會在每套接字一個的錯誤隊列中排隊等待. 當用戶從套接字操做中收到錯誤時,就能夠經過調用設置了
MSG_ERRQUEUE 標識的
recvmsg(2) 來接收. 描述錯誤的
sock_extended_err 結構將經過一條類型爲
IP_RECVERR , 級別爲
SOL_IP的輔助信息進行傳遞. 這個選項對在未鏈接的套接字上可靠地處理錯誤頗有用. 錯誤隊列的已收到的數據部分包含錯誤包.
-
IP 按照下面的方法使用
sock_extended_err 結構: ICMP 包接收的錯誤
ee_origin 設爲
SO_EE_ORIGIN_ICMP , 對於本地產生的錯誤則設爲
SO_EE_ORIGIN_LOCAL .
ee_type 和
ee_code 設置爲 ICMP 頭標識的類型和代碼字段.
ee_info 包含用於
EMSGSIZE 時找到的 MTU.
ee_data 目前沒有使用. 當錯誤來自於網絡時,該套接字上全部IP選項都被激活 (
IP_OPTIONS,
IP_TTL, 等.)而且當作控制信息包含錯誤包中傳遞.引起錯誤的包的有效載荷會以正常數據返回.
-
在
SOCK_STREAM 套接字上,
IP_RECVERR 會有細微的語義不一樣.它並不保存下次超時的錯誤,而是當即傳遞全部進來的錯誤給用戶. 這對 TCP 鏈接時間很短的狀況頗有用,由於它要求快速的錯誤處理. 使用該選項要當心:由於不容許從路由轉移和其它正常條件下正確地進行恢復,它使得TCP變得不可靠,而且破壞協議的規範. 注意TCP沒有錯誤隊列;
MSG_ERRQUEUE 對於
SOCK_STREAM 套接字是非法的. 所以全部錯誤都會由套接字函數返回,或者只返回
SO_ERROR .
-
對於原始(raw)套接字而言,
IP_RECVERR 容許傳遞全部接收到的ICMP錯誤給應用程序,不然錯誤只在鏈接的套接字上報告出來.
-
它設置或者檢索一個整型布爾標識.
IP_RECVERR 缺省設置爲off(關閉).
-
IP_PMTU_DISCOVER
-
爲套接字設置或接收Path MTU Discovery setting(路徑MTU發現設置). 當容許時,Linux會在該套接字上執行定義於RFC1191中的Path MTU Discovery(路徑MTU發現). don't 段標識會設置在全部外發的數據報上. 系統級別的缺省值是這樣的:
SOCK_STREAM 套接字由
ip_no_pmtu_disc sysctl 控制,而對其它全部的套接字都被都屏蔽掉了,對於非
SOCK_STREAM 套接字而言, 用戶有責任按照MTU的大小對數據分塊並在必要的狀況下進行中繼重發.若是設置了該標識 (用
EMSGSIZE ),內核會拒絕比已知路徑MTU更大的包.
Path MTU discovery(路徑MTU發現)標識 |
含義 |
IP_PMTUDISC_WANT |
對每條路徑進行設置. |
IP_PMTUDISC_DONT |
從不做Path MTU Discovery(路徑MTU發現). |
IP_PMTUDISC_DO |
總做Path MTU Discovery(路徑MTU發現). |
當容許 PMTU (路徑MTU)搜索時, 內核會自動記錄每一個目的主機的path MTU(路徑MTU).當它使用 connect(2) 鏈接到一個指定的對端機器時,能夠方便地使用 IP_MTU 套接字選項檢索當前已知的 path MTU(路徑MTU)(好比,在發生了一個 EMSGSIZE 錯誤後).它可能隨着時間的推移而改變. 對於帶有許多目的端的非鏈接的套接字,一個特定目的端的新到來的 MTU 也可使用錯誤隊列(參看 IP_RECVERR) 來存取訪問. 新的錯誤會爲每次到來的 MTU 的更新排隊等待.
當進行 MTU 搜索時,來自數據報套接字的初始包可能會被丟棄. 使用 UDP 的應用程序應該知道這個而且考慮其包的中繼傳送策略.
爲了在未鏈接的套接字上引導路徑 MTU 發現進程, 咱們能夠用一個大的數據報(頭尺寸超過64K字節)啓動, 並令其經過更新路徑 MTU 逐步收縮.
爲了得到路徑MTU鏈接的初始估計,可經過使用 connect(2) 把一個數據報套接字鏈接到目的地址,並經過調用帶 IP_MTU選項的 getsockopt(2) 檢索該MTU.
-
IP_MTU
-
檢索當前套接字的當前已知路徑MTU.只有在套接字被鏈接時纔是有效的.返回一個整數.只有做爲一個
getsockopt(2) 纔有效.
-
IP_ROUTER_ALERT
-
給該套接字全部將要轉發的包設置IP路由器警告(IP RouterAlert option)選項. 只對原始套接字(raw socket)有效,這對用戶空間的 RSVP後臺守護程序之類頗有用. 分解的包不能被內核轉發,用戶有責任轉發它們.套接字綁定被忽略, 這些包只按協議過濾. 要求得到一個整型標識.
-
IP_MULTICAST_TTL
-
設置或者讀取該套接字的外發多點廣播包的生存時間值. 這對於多點廣播包設置可能的最小TTL很重要. 缺省值爲1,這意味着多點廣播包不會超出本地網段, 除非用戶程序明確地要求這麼作.參數是一個整數.
-
IP_MULTICAST_LOOP
-
設置或讀取一個布爾整型參數以決定發送的多點廣播包是否應該被回送到本地套接字.
-
IP_ADD_MEMBERSHIP
-
加入一個多點廣播組.參數爲
struct ip_mreqn 結構.
-
struct ip_mreqn
{
struct in_addr imr_multiaddr; /* IP多點傳送組地址 */
struct in_addr imr_address; /* 本地接口的IP地址 */
int imr_ifindex; /* 接口索引 */
};
-
imr_multiaddr 包含應用程序但願加入或者退出的多點廣播組的地址. 它必須是一個有效的多點廣播地址.
imr_address 指的是系統用來加入多點廣播組的本地接口地址;若是它與
INADDR_ANY 一致,那麼由系統選擇一個合適的接口.
imr_ifindex 指的是要加入/脫離
imr_multiaddr 組的接口索引,或者設爲0表示任何接口.
-
因爲兼容性的緣故,老的
ip_mreq 接口仍然被支持.它與
ip_mreqn 只有一個地方不一樣,就是沒有包括
imr_ifindex 字段.這隻在做爲一個
setsockopt(2) 時纔有效.
-
IP_DROP_MEMBERSHIP
-
脫離一個多點廣播組.參數爲
ip_mreqn 或者
ip_mreq 結構,這與
IP_ADD_MEMBERSHIP 相似. T P
IP_MULTICAST_IF 爲多點廣播套接字設置本地設備.參數爲
ip_mreqn 或者
ip_mreq 結構,它與
IP_ADD_MEMBERSHIP 相似.
-
當傳遞一個無效的套接字選項時,返回
ENOPROTOOPT .
SYSCTLS
IP協議支持 sysctl 接口配置一些全局選項.sysctl可經過讀取或者寫入 /proc/sys/net/ipv4/* 文件或使用 sysctl(2) 接口來存取訪問.
-
ip_default_ttl
-
設置外發包的缺省生存時間值.此值能夠對每一個套接字經過
IP_TTL 選項來修改.
-
ip_forward
-
以一個布爾標識來激活IP轉發功能.IP轉發也能夠按接口來設置
-
ip_dynaddr
-
打開接口地址改變時動態套接字地址和假裝記錄的重寫. 這對具備變化的IP地址的撥號接口頗有用.0表示不重寫,1打開其功能,而2則激活冗餘模式.
-
ip_autoconfig
-
無文檔
-
ip_local_port_range
-
包含兩個整數,定義了缺省分配給套接字的本地端口範圍. 分配起始於第一個數而終止於第二個數. 注意這些端口不能與假裝所使用的端口相沖突(儘管這種狀況也能夠處理). 同時,隨意的選擇可能會致使一些防火牆包過濾器的問題,它們會誤認爲本地端口在使用. 第一個數必須至少>1024,最好是>4096以免與衆所周知的端口發生衝突,從而最大可能的減小防火牆問題.
-
ip_no_pmtu_disc
-
若是打開了,缺省狀況下不對TCP套接字執行路徑MTU發現. 若是在路徑上誤配置了防火牆(用來丟棄全部 ICMP包)或者誤配置了接口 (例如,設置了一個兩端MTU不一樣的端對端鏈接),路徑MTU發現可能會失敗. 寧願修復路徑上的損壞的路由器,也好過整個地關閉路徑MTU發現, 由於這樣作會致使網絡上的高開銷.
-
ipfrag_high_thresh, ipfrag_low_thresh
-
若是排隊等待的IP碎片的數目達到
ipfrag_high_thresh , 隊列被排空爲
ipfrag_low_thresh . 這包含一個表示字節數的整數.
-
ip_always_defrag
-
[kernel 2.2.13中的新功能;在早期內核版本中,該功能在編譯時經過
CONFIG_IP_ALWAYS_DEFRAG 選項來控制]
當該布爾標識被激活(不等於0)時, 來訪的碎片(IP包的一部分,這生成於當一些在源端和目的端之間的主機認定包太大而分割成許多碎片的狀況下)將在處理以前從新組合(碎片整理), 即便它們立刻要被轉發也如此.
只在運行着一臺與網絡單一鏈接的防火牆或者透明代理服務器時才這麼幹; 對於正常的路由器或者主機, 永遠不要打開它. 不然當碎片在不一樣鏈接中經過時碎片的通訊可能會被擾亂. 並且碎片重組也須要花費大量的內存和 CPU 時間.
這在配置了假裝或者透明代理的狀況下自動打開.
-
neigh/*
-
參看
arp(7)
IOCTLS
全部在 socket(7) 中有描述 的 ioctl 均可應用於ip.
用於配置防火牆應用的ioctl記載在 ipchains 包的 ipfw(7) 的文檔中.
用來配置普通設備參數的ioctl在 netdevice(7) 中有描述.
NOTES(備註)
使用 SO_BROADCAST 選項要當心 - 它在 Linux 中沒有權限要求. 不當心的廣播很容易致使網絡過載.對於新的應用協議而言,最好是使用多點廣播組來替代廣播.咱們不鼓勵使用廣播.
有些其它的BSD套接字實現提供了 IP_RCVDSTADDR 和 IP_RECVIF 套接字選項來得到目的地址以及接收數據報的接口.Linux有更通用的 IP_PKTINFO 來完成相同任務.
ERRORS(錯誤)
ENOBUFS,EPERM對EACCES等.)
-
ENOTCONN
-
操做只定義於鏈接的套接字,而該套接字卻沒有鏈接.
-
EINVAL
-
傳遞無效的參數. 對於發送操做,這能夠因發送到一個
blackhole(黑洞) 路由而引起.
-
EMSGSIZE
-
數據報大於該路徑上的 MTU,而且它不能被分紅碎片.
-
EACCES
-
沒有必要權限的用戶試圖執行一項須要某些權限的操做. 這包括: 在沒有
SO_BROADCAST 標識設置的狀況下發送一個包到廣播地址. 經過一條
禁止的 路由發送包. 在沒有
CAP_NET_ADMIN 或者有效用戶標識不爲0的狀況下修改防火牆設置. 在沒有
CAP_NET_BIND_SERVICE 能力或者有效用戶標識不爲零0的狀況下綁定一個保留端口.
-
EADDRINUSE
-
試圖綁定到一個已在使用的地址.
-
ENOMEM 和
ENOBUFS
-
沒有足夠的內存可用.
-
ENOPROTOOPT 和
EOPNOTSUPP
-
傳遞無效的套接字選項.
-
EPERM
-
用戶沒有權限設置高優先級,修改配置或者發送信號到請求的進程或組.
-
EADDRNOTAVAIL
-
請求一個不存在的接口或者請求的源端地址不是本地的.
-
EAGAIN
-
在一個非阻塞的套接字上進行操做會阻塞.
-
ESOCKTNOSUPPORT
-
套接字未配置或者請求了一個未知類型的套接字.
-
EISCONN
-
在一個已經鏈接的套接字上調用
connect(2)
.
-
EALREADY
-
在一個非阻塞的套接字上的鏈接操做已經在進行中.
-
ECONNABORTED
-
在一次
accept(2) 執行中鏈接被關閉.
-
EPIPE
-
鏈接意外關閉或者被對端關閉.
-
ENOENT
-
在沒有報到達的套接字上調用
SIOCGSTAMP .
-
EHOSTUNREACH
-
沒有有效路由表記錄匹配目的地址.該錯誤能夠被來自遠程路由器的 ICMP消息或者由於本地路由表的緣故而引起.
-
ENODEV
-
網絡設備不可用或者不適於發送IP.
-
ENOPKG
-
內核子系統沒有配置.
-
ENOBUFS, ENOMEM
-
沒有足夠的空閒內存. 這經常意味着內存分配因套接字緩衝區的限制而受限, 而不是由於系統內存的緣故,可是這也不是100%正確.
其它錯誤可能由重疊協議族生成;參看 tcp(7), raw(7), udp(7) 和 socket(7).
VERSIONS(版本)
IP_PKTINFO, IP_MTU, IP_PMTU_DISCOVER, IP_PKTINFO, IP_RECVERR 和 IP_ROUTER_ALERT 是Linux 2.2中的新選項.
struct ip_mreqn 也是新出如今Linux 2.2中的.Linux 2.0只支持 ip_mreq.
sysctl是在Linux 2.2中引入的.