accept函数_基础套接字函数入门1
想不想自己寫一個簡單的QQ?想不想自己寫一個聊天室?想不想知道2000年的人是如何上網的?本節講解一些基礎的網絡函數,帶你看看,編寫一個完整的TCP客戶端、服務端需要掌握哪些函數?之后,我們要開發自己的QQ。
1 socket函數
// sys/socket.h /* 使用協議__protocol在域__domain中創建一個__type類型的新套接字。 如果__protocol為零,則自動選擇一個。 返回新套接字的文件描述符,或者返回-1表示錯誤。 */ extern int socket (int __domain, int __type, int __protocol) __THROW;- __domain:即family,AF_INETIPv4協議,AF_INET6IPv6協議
- __type:SOCK_STREAM字節流套接字,SOCK_DGRAM數據報套接字,SOCK_RAW原始套接字
- __protocol:IPPROTO_TCPTCP傳輸協議,IPPROTO_UDPUDP傳輸協議
socket函數在成功時返回一個小的非負整數值,它與文件描述符類似,我們把它稱為套接字描述符(socket descriptor),簡稱socketfd。
AF_前綴表示地址族,PF_前綴表示協議族 ,因為歷史上曾想讓一個協議族(PF)支持多個地址族(AF),用PF來創建套接字,用AF來創建套接字地址結構,然而就只是想想,沒有實現。現在AF和PF的值是相等的。
// bits/socket.h /* Protocol families. */ #define PF_INET 2 /* IP protocol family. */ #define PF_INET6 10 /* IP version 6. */ /* Address families. */ #define AF_INET PF_INET #define AF_INET6 PF_INET62 connect函數
// sys/socket.h #define __CONST_SOCKADDR_ARG const struct sockaddr * extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);- __fd:socket函數返回的套接字描述符
- __addr:指向套接字結構地址的指針
- __len:該套接字的大小
TCP客戶用connect函數和TCP服務器建立連接。客戶在調用connect函數前可以不調用bind函數,因為如果有需要,內核會確定本機IP地址,并選擇一個臨時端口作為源端口。
3 bind函數
// sys/socket.h /* 把一個本地協議地址賦值給一個套接字 */ #define __CONST_SOCKADDR_ARG const struct sockaddr * extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) __THROW;- 對于IPv4來說,協議地址是32位的IPv4地址和16位的端口號組合。
- 對于IPv6來說,協議地址是128位的IPv6地址和16位的端口號組合。
綁定操作涉及3個對象:套接字,地址和端口。其中套接字是捆綁的主體,地址和端口是捆綁的客體。在套接字上綁定地址和端口表示:該地址和端口已經被套接字使用。
- 如果指定端口號為0,那么內核在bind被調用的時候選擇一個臨時端口。
- 如果指定IP地址是通配地址,那么內核將等到套接字已連接(TCP)或在套接字上發出數據報(UDP)時才選擇一個本地IP地址。
對于IPv4來說,通配地址是0(INADDR_ANY),如果讓內核幫套接字選擇一個端口,那么必須注意,bind函數并不返回所選擇的端口號。因為bind函數的_addr參數有const限定詞,它無法返回所選的值。為了拿到內核選擇的臨時端口,必須調用getsockname函數來返回協議地址。
4 listen函數
// sys/socket.h extern int listen (int __fd, int __n) __THROW;listen函數僅有TCP服務器調用,它做兩件事:
- 未完成連接隊列:每個處于三次握手中的TCP連接,套接字處于SYN_RCVD狀態。
- 已完成連接隊列:每個已完成三次握手的TCP連接,套接字處于ESTABLISHED狀態。
這2個隊列之和不能超過__n,否則就無法新建TCP連接,這就是SYN Flood攻擊的原理。
5 accept函數
// sys/socket.h extern int accept (int __fd, __SOCKADDR_ARG __addr,socklen_t *__restrict __addr_len);accept函數由TCP服務器調用,用于從已完成連接隊列的隊頭返回下一個已完成連接。如果該隊列為空,那么進程被投入睡眠。(默認套接字為阻塞方式)
參數__addr和__addr_len返回已連接的對端進程的協議地址,即返回客戶端的協議地址。__addr_len是值-結果參數,返回內核存放在協議地址中實際的字節數。如果對客戶端的協議地址不感興趣,可以將指針置為NULL。
注意:如果accept成功,返回值是又內核自動生成的全新描述符,稱為已連接套接字。服務端與客戶通信,將用這個套接字,服務完成后,這個套接字就被關閉。 而參數__fd稱為監聽套接字, 一個服務僅僅創建一個監聽套接字。6 close函數
// /usr/include/unistd.h extern int close (int __fd);close函數一般可以用來關閉套接字,并終止TCP連接。但是在并發服務器中,close函數僅僅將套接字描述符引用計數減1。所以并不能一定在TCP連接上發送FIN報文,如果想在TCP連接上發送FIN報文,可以用shutdown函數。
參考文獻:《UNIX網絡編程 卷1:套接字聯網API》
總結
以上是生活随笔為你收集整理的accept函数_基础套接字函数入门1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python pypdf2另存为图片_用
- 下一篇: excel 复制数据 sql serve