【UNIX网络编程(二)】基本TCP套接字编程函数
基于TCP客戶/server程序的套接字函數圖例如以下:
運行網絡I/O。一個進程必須做的第一件事就是調用socket函數。指定期望的通信協議類型。
#include <sys/socket.h>
int socket(int family, int type, int protocol);/*返回值:若成功則為非負描寫敘述符,若出錯則為-1*/
socket函數成功時返回一個小的非負整數值,它與文件描寫敘述符類似。把它稱為套接字描寫敘述符,簡稱sockfd。family參數指明協議族。被稱為協議域。type參數指明套接字類型。
protocol參數應該是某個協議類型常值?;蛘邽?,以選擇所給定family和type組合的系統默認值。
各參數列于一下表格:
| family | 說明 | type | 說明 | protocol | 說明 |
| AF_INET | IPv4協議 | SOCKET_STREAM | 字節流套接字 | IPPROTO_TCP | TCP傳輸協議 |
| AF_INET6 | IPv6協議 | SOCK_DGRAM | 數據報套接字 | IPPROTO_UDP | UDP傳輸協議 |
| AF_LOCAL | Unix域協議 | SOCK_SEQPACKET | 有序分組套接字 | IPPROTO_SCTP | SCTP傳輸協議 |
| AF_ROUTE | 路由套接字 | SOCK_RAM | 原始套接字 | ||
| AF_KEY | 秘鑰套接字 |
TCP客戶用connect函數來建立與TCPserver的鏈接。
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen); ?/*返回:若成功則為0。若出錯則為-1*/
sockfd是由socket函數返回的套接字描寫敘述符。第二個、第三個參數各自是一個指向套接字地址結構的指針和該結構的大小??蛻粼谡{用函數connect前不必非得調用bind函數,由于假設須要的話,內核會確定源IP地址,并選擇一個暫時port號作為源port。假設是TCP套接字,調用connect函數將激發TCP的三路握手過程,并且僅在連接建立成功或出錯時才返回,當中出錯返回可能有下面幾種情況:
a、若TCP客戶沒有收到SYN分節的響應,則返回ETIMEDOUT錯誤。
b、若對客戶的SYN的響應是RST(表示復位),則表明該server主機在我們指定的port上沒有進程在等待與之連接。
c、若客戶發出的SYN在中間的某個路由器上引發了一個“destination unreachable”ICMP錯誤。則覺得是一個軟錯誤。
bind函數把一個本地協議地址賦予一個套接字。對于網際網協議,協議地址是32位的IPv4地址與16位的TCP或UDPport號的組合。
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);/*返回,成功則為0,出錯則為-1*/
第二個參數是一個指向特定于協議的地址結構的指針。第三個參數是該地址結構的長度,對于TCP。調用bind函數能夠指定一個port號?;蛑付ㄒ粋€IP地址,也能夠兩者都指定。還能夠都不指定。
server在啟動時捆綁它們的眾所周知port。假設一個TCP客戶或server未曾調用bind捆綁一個port,當調用connect或listen時。內核就要為對應的套接字選擇一個暫時port號。讓內核選擇暫時port對于TCP客戶來說是正常的。除非應用須要一個預留port;而毀于TCPserver來說卻極為罕見,由于server是通過他們的眾所周知port被大家認識的。
進程能夠把一個特定的IP地址捆綁到它的套接字上,只是這個IP地址必須屬于其所在主機的網絡接口之中的一個。
假設指定port號為0,那么內核就bind被調用時選擇一個暫時port。然而假設指定IP地址為通配地址。那么內核將等到套接字已連接TCP或已在套接字上發出數據報時才選擇一個IP地址。對于IPv4來說,通配地址由常量INADDR_ANY來指定,其值為0。
注意:假設讓內核來為套接字選擇一個暫時port號,那么必須注意。函數bind并不返回所選擇的值。實際上。因為bind函數的第二個參數有const限定詞,它無法返回所選之值。
為了得到內核所選擇的這個暫時port值,必須調用函數getsockanme來返回協議地址。
listen函數僅由TCPserver調用,它做兩件事:
1、當socket函數創建一個套接字時,它被如果為一個主動套接字,也就是說。它是一個將調用connect發起連接的客戶套接字。listen函數把一個未連接的套接字轉換成一個被動套接字,指示內核應該受指向該套接字的連接請求。
2、本函數的第二個參數規定了內核應該為對應套接字排隊的最大連接個數。
#include <sys/socket.h>
int listen(int sockfd, int backlog);/*返回:若成功則為0。出錯則為-1*/
本函數通常應該在調用socket和bind這兩個函數之后。并在調用accept函數之前調用。
為理解backlog參數。必須認識到內核為不論什么一個給定的監聽套接字維護兩個隊列:
1、未完畢連接隊列。每一個這種SYN分節相應當中一項:已由某個客戶發出并到達server,而server正在等待完畢相應的TCP三路握手過程,這些套接字處于SYN_RCVD狀態
2、已完畢連接隊列,每一個已完畢TCP三路握手過程的客戶相應當中一項。這些套接字處于ESTBLISHED狀態。
accept函數由TCPserver調用,用于從已完畢連接隊列返回下一個已完畢連接。假設已完畢連接隊列為空,那么進程被投入睡眠。
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen); ? /*返回:若成功則為負描寫敘述符。若出錯則為-1*/
參數cliaddr和addrlen用來返回已連接的對端進程協議地址。假設accept成功,那么其返回值是由內核自己主動生成的一個全新描寫敘述符,代表與所返回客戶的TCP鏈接。在討論accept函數時,稱第一個參數為監聽套接字描寫敘述符。稱返回值為已連接套接字描寫敘述符。區分這兩個套接字很重要。
一個server通常只創建一個監聽套接字,它在該server的生命周期內一直存在。
內核為每一個由server進程接受的客戶連接創建一個已連接套接字。當server完畢對某個給定客戶的服務時,對應的一兩節套接字就被關閉。
本函數最多返回3個值:一個既可能是新套接字描寫敘述符也可能是出錯僅僅是的整數、客戶進程的協議地址以及該地址的大小。假設對返回客戶協議地址不感興趣,能夠把cliaddr和addrlen均置為空指針。
close函數用來關閉套接字。并終止TCP連接。int close(int sockfd)。返回:成功則為0。出錯則為-1。
轉載于:https://www.cnblogs.com/mfrbuaa/p/5225231.html
總結
以上是生活随笔為你收集整理的【UNIX网络编程(二)】基本TCP套接字编程函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 22.网络提速(最短路)
- 下一篇: JConsole监控远程Tomcat服务