編寫乙個完整的tcp客戶/伺服器程式需要一些基本的套接字函式
下面依次介紹上圖中涉及的基本套接字函式(read()和write()在此不做複述)
socket函式
為執行網路i/o,首先要呼叫socket()函式指定期望的通訊型別
family:指定協議族
type:指定套接字型別
protocol:或為協議型別常值或為0
ps:family和type的組合只有部分有效
socket函式在成功後返回乙個小的非負整數值,它與檔案描述符類似,稱為套接字描述符-sockfd
#include int socket(int family, int type, int protocol);
//成功返回非負描述符,出錯返回-1
socket()的family常值
family
說明af_inet
ipv4協議
af_inet6
ipv6協議
af_local
unix域協議
af_route
路由套接字
af_key
金鑰套接字
socket()的type常值
type
說明sock_stream
位元組流套接字
sock_dgram
資料報套接字
sock_seqpacket
有序分組套接字
sock_raw
原始套接字
socket()ipv4和ipv6的protocol常值
protocol
說明ipproto_tcp
tcp傳輸協議
ipproto_udp
udp傳輸協議
ipproto_sctp
sctp傳輸協議
socket()中family和type引數的組合
af_inet
af_inet6
af_local
af_route
af_key
sock_stream
tcp|sctp
tcp|sctp
是sock_dgram
udpudp
是sock_seqpacket
sctp
sctp
是sock_raw
ipv4
ipv6是是
connect()函式
tcp客戶用connect函式來建立與tcp伺服器的連線
#include int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
//成功返回0,出錯返回-1
sockfd:socket()返回的描述符
servaddr:含有伺服器ip位址和埠號的套接字結構指標
addrlen:套接字結構的大小
如果是tcp套接字,呼叫connect函式後會激發三路握手過程,而且僅在成功或出錯後返回
出錯情況
1》客戶沒有收到syn分節的響應,則返回etimedout錯誤,有些系統提供對超時值的管理性控制
2》客戶收到的syn響應是rst(復位),返回econnrefused錯誤,這是一種「硬錯誤」,表明伺服器主機在我們指定的埠上沒有程序在等待與之連線
3》若客戶發出的syn在中間的某個路由器上引發了乙個「destination unreachable」(目的地不可達)icmp錯誤,則認為是一種軟錯誤,客戶主機核心儲存訊息後按某個時間間隔繼續傳送,若仍未收到響應,把儲存的icmp錯誤作為ehostunreach或enetunreach錯誤返回給程序,還有兩種可能的情況:一是按照本地系統的**表沒有路徑,二是connect呼叫不等待就返回。
bind函式
bind函式把乙個本地協議位址賦予乙個套接字
#include int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
//成功返回0,出錯返回-1
myaddr:指向特定於協議的位址結構的指標
呼叫bind函式可以指定乙個埠號,或指定乙個ip位址,也可以都指定或都不指定
1》伺服器在啟動時**它們的總所周知埠,如果沒有**,核心會進行分配
2》程序可以把乙個特定的ip位址**到它的套接字上,不過這個ip位址必須屬於其所在主機的網路介面之一
當連線套接字時,核心根據所用的外出介面指定源ip,所用的外出介面則取決於到達伺服器的路徑,
如果tcp伺服器沒有指定ip位址,就把接收的syn的目的位址作為伺服器的源ip位址
bind函式繫結的結果
程序指定
結果ip位址
埠通配位址
0核心選擇ip位址和埠
通配位址
!0核心選擇ip位址,程序指定埠
本地ip
0程序指定ip位址,核心選擇埠
本地ip
!0程序指定ip位址和埠
對ipv4來說,通配位址由inaddr_any指定,其值一般為0,它告訴核心取選擇ip位址
struct sockaddr_in servaddr;
servaddr.sin_addr.s_addr = htonl(inaddr_any);
但對ipv6,128位的位址存放在乙個陣列中,所以系統預先分配in6addr——any並將其宣告為inaddr_any_init常值
//struct sockaddr_in6 serv
serv.sin6_addr = in6addr_any;
listen函式
listen函式僅有tcp伺服器呼叫,它做兩件事
1》當socket函式建立乙個套接字時,預設為主動套接字,即客戶端套接字,listen將其轉變為被動套接字,指示核心應接受指向該套接字的連線請求。
2》本函式的第二個引數規定了核心應為相應套接字排隊的最大連線個數
#include int listen(int sockfd, int backlog);
//成功則為0,出錯則為-1
兩個佇列:
未完成佇列:syn分節已由客戶發出並到達伺服器,而伺服器正在等待完成相應的tcp三路握手過程,處於syn_rcvd狀態
已完成佇列:每個完成三路握手過程的客戶對應其中一項
兩佇列之和不超過backlog
注意:1》不要把backlog設定為0,如果不想任何人連線,就關閉這個監聽套接字
2》對backlog可以指定乙個比核心能夠支援的值還要大的值,核心會截斷為自身可以接受的最大值
3》當乙個客戶syn到達時,如果佇列是滿的,tcp忽略該分節,等待重發
accept函式
accept函式由tcp伺服器呼叫,用於從已完成連線佇列隊頭返回下乙個已完成連線的客戶,如果已完成連線隊列為空,該函式被投入睡眠(阻塞狀態)
#include int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
//成功返回非負描述符,出錯為-1
如果accept成功,返回的是乙個由核心生成的,代表與所返回客戶的tcp連線。
兩個描述符:
1》監聽套接字:由socket建立,作為accept的第乙個引數,乙個伺服器通常僅僅建立乙個
2》已連線套接字,accept的返回值,核心為每個由伺服器程序接受的客戶連線建立乙個已連線套接字
網路套接字程式設計
1。位元組序 小位元組 低位儲存在低位元組 大位元組 低位儲存在高位元組 簡單程式判斷 int islittle 2.hostent結構 struct hostent define h addr h addr list 0 這裡是這個資料結構的詳細資料 struct hostent h name 位...
網路程式設計套接字
建立 函式原型 int socket int domain int type int protocol 引數說明 domain 協議域,又稱協議族 family 常用的協議族有af inet af inet6 af local 或稱af unix,unix域socket af route等。協議族決...
網路程式設計套接字
本節重點 本節重點需要掌握的是 基本概念 1.認識ip位址 同樣的問題,整個西天取經過程中,直到ip位址 從長安到西天 只知道這個不能完成取經 需要直到從長安的誰那得到的資訊到西天的誰那拿經 唐太宗 如來佛 有了ip位址 長安 西天 和埠號 唐太宗 如來佛 才能完成取經。引出了下面的埠號的概念。2....