1、基礎知識。linux
1:套接字基礎。數據庫
1,是通訊端點的抽象。服務器
2,在UNIX類系統中被看成是一種文件描述符。網絡
3,套接字通訊域。dom
域 | 描述 |
AF_INET | IPV4因特網域 |
AF_INET6 | IPV6因特網域 |
AF_UNIX | UNIX域 |
AF_UPSPEC | 未指定 |
4,套接字類型。異步
類型 | 描述 |
SOCK_DGRAM | 固定長度的,無連接的,不可考的報文傳遞 |
SOCK_RAW | IP協議的數據報接口 |
SOCK_SEQPACKET | 固定長度的,有序的,可靠的,面向鏈接的報文傳遞。 |
SOCK_STREAM | 有序的,可靠的,雙向的,面向鏈接的字節流。 |
5,協議。socket
協議 | 描述 |
IPPROTO_IP | IPv4網際協議 |
IPPROTO_IPV6 | IPv6網際協議 |
IPPROTO_ICMP | 因特網控制報文協議(internet control message protocol) |
IPPROTO_RAW | 原始IP數據包協議 |
IPPROTO_TCP | 傳輸控制協議 |
IPPROTO_UDP | 用戶數據報協議(user datagram protocol) |
6,建立一個原始套接字須要root權限。函數
2:套接字尋址和傳輸。ui
1,在網絡中,進程標識由:計算機網絡地址(找到計算機) + 計算機的端口號(找到特定進程) 組成。spa
2,大端和小端。
1)大端字節序:最大字節地址上 保存 最低有效字節。
2)小端字節序:最大字節地址上 保存 最高有效字節。
3)大部分系統使用小端字節序。但TCP/IP使用大端字節序。
3,域名系統( Domain name system,DNS)
4,網絡信息服務( Network information service, NIS )
5,服務是由地址的端口號部分標示。每一個服務由一個惟一的端口號支持。
6,章16的代碼在閱讀結束後,進行嘗試性理解和自編寫。
7,當異步IO中由於某種緣由致使讀/寫阻塞,在阻塞條件不存在後,能夠發送SIGIO信號來從新啓用IO。步驟爲:
1)創建套接字全部權。這樣信號能夠被傳遞到對應的進程。
2)通知套接字當IO操做不會阻塞時發送信號。
8,帶外數據
1)含義:緊急數據。它有相對普通數據更高的優先級。
2)部分通訊協議支持此功能。(可選功能)
3)當有新的緊急數據到來,舊有數據會被覆蓋。
3:套接字選項。
1,套接字機制提供了 兩個套接字選項接口:設置選項接口,查詢選項接口。
4:UNIX域套接字。
1,IPC的一種:能夠在同一計算機系統上運行的兩個進程之間傳遞打開文件描述符。
1)用於同一臺計算機的進程通訊。
2)效率比因特網套接字高。由於它僅複製數據,無協議,無校驗等複雜操做。
2,一些實例(未閱讀)。
1)P508,藉助UNIX域套接字輪詢XSI消息隊列。
2)P512,將地址綁定到UNIX域套接字。
3)P518,傳送文件描述符:在兩個進程之間傳送打開文件描述符的技術很是有用。
3,sockaddr_un結構體。
1)能夠將一個地址綁定到UNIX域套接字上。系統會使用該路徑建立一個S_IFSOCK類型的文件。此文件沒法打開。當關閉套接字時,必須顯式的刪除文件。
2、相關函數。
1:套接字。
1 建立一個套接字 int socket( int domain, int type, int protocol ); // 1 參數protocol:一般爲0。表示使用默認協議。 2 禁止一個套接字IO int shutdown( int sockfd, int how ); // 1 參數how:SHUT_RD,SHUT_WR,SHUT_RDWR
2:尋址。
1 處理器字節序 和 網絡字節序 的轉換。 uint32_t htonl( uint32_t hostint32 ); uint16_t htons( uint16_t hostint16 ); uint32_t ntohl( uint32_t netint32 ); uint16_t ntohl( uint16_t netint16 ); // 1 h 主機,n 網絡,l 長整數,s 短整數。 2 地址通用結構體。 struct socketaddr { sa_family_t sa_family; // address family char sa_data[]; // variable-length address ... } 3 網絡地址的 二進制地址 和 文本字符串 相互轉換 const char *inet_ntop( int domain, const void *restrict addr, char *restrict str, socklen_t size ); // 二進制地址 轉換成 文本字符串 int inet_pton( int domain, const char *restrict str, void *restrict addr ); // 文本字符串 轉換成 二進制地址。 4 查詢主機信息。 struct hostent* gethostent( void ); void sethostent( int stayopen ); void endhostent( void ); struct hostent { char *h_name; // name of host char **h_aliases; // pointer to alternate host name array int h_addrtype; // address type int h_length; // length in bytes of address char **h_addr_list; // pointer to array of network address ... } 5 獲取網絡名字 和 網絡編號。 struct netent* getnetbyaddr( uint32_t net, int type ); struct netent* getnetbyname( const char *name ); struct netent* getnetent( void ); void setnetent( int stayopen ); void endnetent( void ); struct netent{ char *n_name; // network char **n_aliases; // alternate network name array pointer int n_addrtype; // address type uint32_t n_net // network number ... } 6 協議名字和協議編號之間進行映射。 struct protoent* getprotobyname( const char *name ); struct protoent* getprotobynumber( int proto ); struct protoent* getprotoent( void ); void setprotoent( int stayopen ); void endprotoent( void ); struct protoent{ char *p_name; // protocol name char **p_aliases; // pointer to altername protocol name array int p_proto; // protocol number ... } 7 函數getservent順序掃描服務數據庫。 struct servent* getservbyname( const char *name, const char *proto ); struct servent* getservbyport( int port, const char *proto ); struct servent* getservent( void ); void setservent( int stayopen ); void endservent( void ) struct servent{ char s_name; // service name char **s_aliases; // pointer to alternate service name array int s_port; // port name char *s_proto; // name of protocol ... } 8 將主機名和服務名映射到一個地址。 int getaddrinfo( const char *restrict host, const char *restrict service, const struct addrinfo *restrict hint, struct addrinfo **restrict res ); void freeaddrinfo( struct addrinfo *ai ); struct addrinfo{ int ai_flags; // custemize behavior int ai_family; // address family int ai_socktype; // socket type int ai_protocol; // protocol socklen_t ai_addrlen; // length in bytes of address struct sockaddr *ai_addr; // address char *ai_canonname; // canonical name of host struct addrinfo *ai_next; // next in list ... } 9 將返回的錯誤碼轉換成錯誤信息 consr char *gai_strerror( int error ); 10 將地址轉換成 主機名 和 服務名 int getnameinfo( const struct sockaddr *restrict addr, socklen_t alen, char *restrict host, socklen_t hostlen, char *restrict service, socklen_t servlen, int flags );
3:套接字 和 地址關聯。
1 綁定 關聯地址 和 套接字。 int bind( int sockfd, const struct sockaddr *addr, socklen_t len len ); // 1 地址必須有效,且格式匹配。 // 2 端口通常不小於1024.root權限用戶除外。 // 3 通常不容許多重綁定。 2 查找 套接字對應的地址。 int getsockname( int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp ); 3 找到和套接字鏈接的對等方地址。 int getpeername( int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp ); 4 (請求服務端)創建鏈接。 int connect( int sockfd, const struct sockaddr *addr, socklen_t len ); // 1 參數addr:指望通訊的服務器地址。 // 2 應用程序必須可以處理connect函數返回的錯誤。 5 (接收信息端)接收鏈接請求。 int listen( int sockfd, int backlog ); 6 得到鏈接請求,並創建鏈接。 int accept( int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len ); // 1 返回值:套接字描述符。
4:數據傳輸。
1 發送數據。 ssize_t send( int sockfd, const void *buf, size_t nbytes, int flags ); // 套接字必須已經鏈接。 // 1 返回成功,僅表明發送成功。接收錯誤不反饋。 ssize_t sendto( int sockfd, const void *buf, size_t nbytes, int flags, const struct sockaddr *destaddr, socklen_t destlen ); // 能夠在無鏈接套接字上發送信息。 ssize_t sendmsg( int sockfd, const struct msghdr *msg, int flags, ); // 能夠指定多重緩衝區傳輸數據。 2 接收數據。 ssize_t recv( int sockfd, void *buf, size_t nbytes, int flags ); // ssize_t recvfrom( int sockfd, void *restrict buf, size_t len, int flags, struct sockaddr *restrict addr, socklen *restrict addrlen ); // 獲得數據發送者的原地址 ssize_t recvmsg( int sockfd, struct msghdr *msg, int flags ); // 將接收數據送入多個緩衝區
5:套接字選項。
1 設置套接字選項。 int setsockopt( int sockfd, int level, int option, const void *val, socklen_t len ); // 1 參數level:標識選項應用協議。 2 查看當前選項。 int getsockopt( int sockfd, int level, int option, void *restrict val, socklen_t *restrict lenp ); // 1 參數level:標識選項應用協議。
6:帶外數據。
1 TCP中,判斷是否已經到達緊急數據標記位置。 int sockarmark( int sockfd ); // 1 返回值:1 在標記處,0 不在標記處,-1 出錯
7: UNIX域套接字。
1 建立一對無命名的,相互鏈接的UNIX域套接字。(通常只用於UNIX域。) int socketpair( int domain, int type, int protocol, int sockfd[2] ); // 打開的爲全雙工管道。 // 1 返回值:0 成功,-1 出錯。 2 sockaddr_un 結構體。 struct sockaddr_un { sa_family_t sun_family; // AF_UNIX char sun_path[108]; // pathname } // OS:linux and solaris。 Head file name is "sys/un.h";
三