linux高效能伺服器程式設計---第五章Linux網路程式設計基礎API (3)
阿新 • • 發佈:2022-05-06
通用讀寫函式
#inclued <sys/socket.h> ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags); ssize_t sendmsg(int sockfd, struct msghdr* msg, int flags); struct msghdr { /* socket address --- 指向socket地址結構變數, 對於TCP連線需要設定為NULL*/ void* msg_name; socklen_t msg_namelen; /* 分散的記憶體塊 --- 對於 recvmsg來說資料被讀取後將存放在這裡的塊記憶體中, 記憶體的位置和長度由 * msg_iov指向的陣列指定, 稱為分散讀(scatter read) ---對於sendmsg而言, msg_iovlen塊的分散記憶體中 * 的資料將一併傳送稱為集中寫(gather write);*/ struct iovec* msg_iov; int msg_iovlen; /* 分散記憶體塊的數量*/ void* msg_control; /* 指向輔助資料的起始位置*/ socklen_t msg_controllen; /* 輔助資料的大小*/ int msg_flags; /* 複製函式的flags引數, 並在呼叫過程中更新*/ }; struct iovec { void* iov_base /* 記憶體起始地址*/ size_t iov_len /* 這塊記憶體長度*/ }
其他Api
#include <sys/socket.h> //用於判斷 sockfd是否處於帶外標記, 即下一個被讀取到的資料是否是帶外資料, // 是的話返回1, 不是返回0 // 這樣就可以選擇帶MSG_OOB標誌的recv呼叫來接收帶外資料. int sockatmark(int sockfd); // getsockname 獲取sockfd對應的本端socket地址, 存入address指定的記憶體中, 長度存入address_len中 成功返回0失敗返回-1 // getpeername 獲取遠端的資訊, 同上 int getsockname(int sockfd, struct sockaddr* address, socklen_t* address_len);int getpeername(int sockfd, struct sockaddr* address, socklen_t* address_len); /* 以下函式標頭檔案均相同*/ // sockfd 目標socket, level執行操作協議(IPv4, IPv6, TCP) option_name 引數指定了選項的名字. 後面值和長度 // 成功時返回0 失敗返回-1 int getsockopt(int sockfd, int level, int option_name, void* option_value, socklen_t restrict option_len); int setsockopt(int sockfd, int level, int option_name, void* option_value, socklen_t restrict option_len);
SO_REUSEADDR | 重用本地地址 | sock被設定此屬性後, 即使sock在被bind()後處於TIME_WAIT狀態, 此時與他繫結的socket地址依然能夠立即重用來繫結新的sock |
---|---|---|
SO_RCVBUF | TCP接收緩衝區大小 | 最小值為256位元組. 設定完後系統會自動加倍你所設定的值. 多出來的一倍將用用作空閒緩衝區處理擁塞 |
SO_SNDBUF | TCP傳送緩衝區大小 | 最小值為2048位元組 |
SO_RCVLOWAT | 接收的低水位標記 | 預設為1位元組, 當TCP接收緩衝區中可讀資料的總數大於其低水位標記時, IO複用系統呼叫將通知應用程式可以從對應的socket上讀取資料 |
SO_SNDLOWAT | 傳送的高水位標記 | 預設為1位元組, 當TCP傳送緩衝區中空閒空間大於低水位標記的時候可以寫入資料 |
SO_LINGER |
struct linger { int l_onoff /* 開啟非0, 關閉為0*/ int l_linger; /* 滯留時間*/ /* * 當onoff為0的時候此項不起作用, close呼叫預設行為關閉socket * 當onoff不為0 且linger為0, close將立即返回, TCP將丟棄傳送緩衝區的殘留資料, 同時傳送一個復位報文段 * 當onoff不為0 且linger大於0 . 當socket阻塞的時候close將會等待TCP模組傳送完殘留資料並得到確認後關 * 閉, 如果是處於非阻塞則立即關閉 */ };
網路資訊API
#include <netdb.h> // 通過主機名查詢ip struct hostent* gethostbyname(const char* name); // 通過ip獲取主機完整資訊 // type為IP地址型別 AF_INET和AF_INET6 struct hostent* gethostbyaddr(const void* addr, size_t len, int type); struct hostent { char *h_name; /* Official name of host. */ char **h_aliases; /* Alias list. */ int h_addrtype; /* Host address type. */ int h_length; /* Length of address. */ char **h_addr_list; /* List of addresses from name server. */ } int main(int argc, char* argv[]) { if (argc != 2) { printf("非法輸入\n"); exit(0); } char* name = argv[1]; struct hostent *hostptr{}; hostptr = gethostbyname(name); if (hostptr == nullptr) { printf("輸入存在錯誤 或無法獲取\n"); exit(0); } printf("Official name of hostptr: %s\n", hostptr->h_name); char **pptr; char inet_addr[INET_ADDRSTRLEN]; printf("Alias list:\n"); for (pptr = hostptr->h_aliases; *pptr != nullptr; ++pptr) { printf("\t%s\n", *pptr); } switch (hostptr->h_addrtype) { case AF_INET: { printf("List of addresses from name server:\n"); for (pptr = hostptr->h_addr_list; *pptr != nullptr; ++pptr) { printf("\t%s\n", inet_ntop(hostptr->h_addrtype, *pptr, inet_addr, sizeof(inet_addr))); } break; } default: { printf("unknow address type\n"); exit(0); } } return 0; } /* ./run baidu.com Official name of hostptr: baidu.com Alias list: List of addresses from name server: 39.156.69.79 220.181.38.148 */