網絡IPC:套接字

函數摘要

函數 說明 成功 失敗
建立套接字
socket 建立一個套接字 文件(套接字)描述父 -1
getsockename 獲取套接字的綁定地址 0 -1
getpeername 獲取對方的地址 0 -1
shudown 禁用一個套接字的I/O的讀寫功能 0 -1
htonl、htons 機器字節序和網絡字節序之間實現轉換 以網絡字節序表示的32/16位整數 -1
inet_ntop、inet_pton 網絡字節順序的地址轉換(二進制<---->文本字符串格式) 地址字符串指針/格式無效 -1
網絡地址信息
gethostent 查詢網絡地址信息 指針 NULL
sethostent 會打開文件,若是文件被打開,將其迴繞
endhostent 關閉文件
getprotobyname 協議名稱和協議號之間映射 指針 NULL
getprotobynumber
getproto
getservbyname 服務器名和端口 指針 NULL
getservbyport
getservbynet
getaddrinfo 將一個主機名和一個服務器名的關係映射到一個地址空間 0 非0錯誤碼
freeaddrinfo 釋放緩衝空間
get_strerror 將getaddrinfo失敗的錯誤碼轉換成錯誤消息 指向描述錯誤的字符串的指針
getnameinfo 套接字地址(addr)被翻譯成一個主機名和一個服務器名映射到一個地址 0 非0錯誤碼
服務器
bind 關聯服務器地址和套接字 0 -1
listen 監聽 0 -1
accept 阻塞直到得到客戶端請求並創建鏈接 文件(套接字)描述符,參數中地址獲取客戶端地址 -1
客戶端
connect 鏈接服務器地址 0 -1
數據傳輸
send 發送 放回發送的字節數 -1
sendto sendto能夠在無鏈接的套接字上指定一個目標地址 放回發送的字節數 -1
sendmsg 調用帶有msghdr結構的sengmsg來指定多重緩衝區數據,和writev函數類似 放回發送的字節數 -1
recv 接受 返回數據的字節長度;若無可用數據或對等方已經按序結束,返回0 -1
recvfrom 接受 返回數據的字節長度;若無可用數據或對等方已經按序結束,返回0 -1
recvmsg 從指定多重緩衝區數據接受帶有msghdr結構的sengmsg來,和readv函數類似 返回數據的字節長度;若無可用數據或對等方已經按序結束,返回0 -1
套接字選項
setsockopt 設置套接字選項 0 -1
getsockopt 獲取套接字選項 0 -1

名稱解釋

套接字描述符

  • 套接字描述符:套接字是通訊端點的抽象。在UNIX系統中被看成是一種文件描述符,能夠在上面直接使用I/O函數(read/write)。

尋址

  • 字節順序:一個處理器架構特性,用於指示像整數這樣的大數據類型的字節如何排序。
    • 大端(big-endian):最大字節地址出如今最低有效字節(Least Significant Byte,LSB)上。
    • 小端(little-endian):最小字節地址出如今最低有效字節(Least Significant Byte,LSB)上。
    • TCP/IP協議棧使用了大端字節序。

輸入圖片說明

地址格式:

  • 不一樣通訊域有不一樣的地址格式:一個地址標識一個特定通訊域的套接字端點。
  • 爲使不一樣格式地址可以傳入到套接字函數,地址強制轉換成通用結構sockaddr
struct sockaddr {
    sa_family_t     sa_family;  /*地址協議:ipv四、ipv六、*//
    char            sa_data[];  /*地址變量長度*/
    ...
}
// linux的地址格式
struct sockaddr_t   {
    sa_family_t sin_family; /*地址協議:ipv四、ipv六、*/
    in_port_t sin_port; /*端口號*/
    struct in6_addr sin6_addr; /*IPv4 address*/
    unsigned char sin_size[8]; /*filer*/
}

地址查詢:

  • 理想狀態下應用程序不須要了解一個套接字地址的內部結構,通常把地址信息存在:linux

    • 靜態文件:/etc/hosts和/etc/services
    • 網上服務器:域名系統(Domain Name System,DNS)或網絡信息服務(Network Information Service,NIS)

套接字選項

  • 通用選項,工做在全部套接字
  • 套接字層次管理的選項,可是依賴於下層協議的支持。
  • 特定於某協議的選項,每一個協議獨有的。

帶外數據

  • 帶外數據(out-of-band data):是一些同i性能協議所支持的可選功能,與普通數據相比,它語序更高優先級的數據傳送。
    • TCP將帶外數據稱爲緊急數據(urgent data):TCP僅支持一個字節的緊急數據,若是帶MSG_OOB標誌發送的字節數超過一個,最後一個字節將唄視爲緊急數據字節。
    • 3個send函數中的任意一個裏指定了MSG_OOB標誌。

非阻塞和異步I/O

  • recv沒有數據可用時會阻塞等待。當套接字輸出隊列沒有足夠空間來發送消息時,send函數會阻塞。
  • 啓動異步I/O的過程:
    • 創建套接字全部權,這樣信號能夠唄傳遞到合適的進程
      • fcntl中使用F_SETOWN
    • 通知套接字當I/O操做不會阻塞時發信號。
      • fcntl中使用F_SETFL命令而且啓用文件標誌O_ASYNC

函數詳情

socket:建立一個套接字

#include <sys/socket.h>

int socket(int domain,int type,int protocal);

    -- '成功:文件(套接字)描述父;出錯:-1'
  • 參數:數據庫

    • domain: 肯定通訊的特性,包括域,以及每種域不一樣的地址格式
    • type套接字的類型,進一步肯定通訊特徵。
    • protocal: 爲給定的域和套接字類型選擇默認協議,一般爲0
描述
AF_INET IPv4因特網域
AF_INET6 IPv6因特網域
AF_UNIX UNIX域
AF_UPSPEC 未指定

|類型|描述| |:--|:--| |SOCK_DGRAM|固定長度、無鏈接的、不可靠的報文傳遞(UDP)| |SOCK_RAW|IP協議的數據報接口| |SOCK_SEQPACKET|固定長度、有序的、可靠的、面向鏈接的報文傳遞| |SOCK_STREAM|有序的、可靠的、雙向的、面向鏈接的字節流(TCP)|數組

協議 描述
IPPROTO_IP IPv4網際協議
IPPROTO_IP6 IPv6網際協議
IPPROTO_ICMP 英特網控制報文協議(Internet Control Message Protocol)
IPPROTO_RAW 原始IP數據包協議
IPPROTO_TCP 促昂數控制協議
IPPROTO_UDP 用戶數據報協議(User Datagram Protocol)
  • 特色:服務器

    • 和open相似,獲取可用於I/O操做的文件描述符。
    • lseek不能以套接字描述符爲參數,由於套接字不支持文件描述符偏移量的概念。
    • SOCK_DGRAM:兩個對等進程之間通訊時不須要邏輯鏈接,只須要向對等進程所使用的套接字發送一個報文。例如:數據報是自含報文,像郵寄信件
    • SOCK_STREAM:要求在本地套接字和通訊的對等進程的套接字之間創建一個邏輯鏈接,套接字提供字節流服務,因此應用程序分辨不出報文的界限。例如: 面向鏈接向打電話

shudown:禁用一個套接字的I/O

#include <sys/socket.h>

int shutdown(int sockfd, int how);

    -- '成功:0;失敗:-1'
  • 參數:網絡

    • how:操做方式
      • SHUT_RD:關閉讀端,沒法從套接字讀取數據。
      • SHUT_WR:關閉寫端,沒法使用套接字發送數據。
      • SHUT_RDWR:沒法讀寫。
  • 特色:架構

    • close:必需要全部的活動引用都關閉,纔會徹底釋放。當屢次dup的時候,能夠用shutdown來直接關閉套接字描述符。

機器字節序和網絡字節序之間實現轉換

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostint32); '返回值:以網絡字節序表示的32位整數'

uint16_t htons(uint16_t hostint16); '返回值:以網絡字節序表示的16位整數'

uint32_t ntonl(uint32_t hostint32); '返回值:以主機字節序表示的32位整數'

uint16_t ntons(uint16_t hostint16); '返回值:以主機字節序表示的16位整數'

網絡字節順序的地址轉換(二進制<---->文本字符串格式)

#include <arpa/inet.h>

const char *inet_ntop(int domain, const void *restrict addr, char *restrict str, socklen_t size);    
    
        -- '成功:地址字符串指針;出錯:NULL'
        
const char *inet_pton(int domain, const char *restrict str, void *restrict addr);     
        -- '成功:1;格式無效:0;出錯:-1'
  • 特色:dom

    • inet_ntop:將網絡字節序的二進制地址轉換成文本字符串格式。
    • inet_pton:將文本字符串格式轉換成網絡字節序的二進制地址。

網絡地址信息

查詢
#include <netdb.h>

struct hostent *gethostent(void);

     -- '成功:指針;出錯:NULL'

void sethostent(int stayopen);      '會打開文件,若是文件被打開,將其迴繞'

void endhostent(void);          '關閉文件'

//hostent結構

struct hostnet {
    char *h_name;           /* name of host*/
    char **h_aliases;       /* pointer to alernate 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 addresses */
    ...
}
  • 特色:gethostent每次調用都會刷新緩衝區。

協議名稱和協議號之間映射

#include <netdb.h>

struct protoent *getprotobyname(const char *name);

struct protoent *getprotobynumber(int proto);

struct protoent *getproto(void);
    
    -- '成功:返回指針;出錯:NULL'
    
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 */
    ...
}
服務器名和端口
#include <netbd.h>

struct servent *getservbyname(const char *name, const char *proto); 

struct servent *getservbyport(int port, const char *proto);

struct servent *getservbynet(void);

    --'成功:指針;出錯:NULL'
    
void setprotoent(int stayopen);

void endprotoent(void);

struct servent {
    char *p_name;           /* protocol name */
    char **p_aliases;       /* pointer to altername protocol name array */
    int  p_port;            /* port number */
    int  *s_proto;          /* name of protocol */
    ...
}
  • 特色:異步

    • getservbyname:將一個服務名映射到一個端口號。
    • getservbyport:將一個端口號映射到一個服務名。
    • getservbynet: 順序少買服務數據庫。
getaddrinfo、freeaddrinfo: 將一個主機名和一個服務器名映射到一個地址
#include <sys/socket.h>
#include <netdb.h>

int getaddrinfo(const char *restrict host, const char *restrict service, const struct addrinfo *restrict hint, struct addrinfo **restrict res);

    -- '成功:0;出錯:非0錯誤碼'
    
void freeaddrinfo(struct addrinfo *ai);

struct addrinfo {
    int         ai_flags;            /*customize behavior */
    int         ai_family;           /* address family */
    int         ai_socketype;        /* 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  */
    ...
}
  • 參數:socket

    • ai_flags
標誌 描述
AI_ADDRCONFIG 查詢配置的地址類型(IPv4或IPv6)
AI_ALL 查詢IPv4或IPv6地址
AI_CANONNAME 須要一個規範的名字(與別名相對)
AI_NUMERICHOST 以數字格式指定主機地址,不翻譯
AI_NUMERICSERV 以服務指定爲數字端口號,不翻譯
AI_PASSIVE 套接字地址用於監聽綁定
AI_V4MAPPED 若是沒有找到IPv6地址,返回映射到IPv6個數的IPv4地址
get_strerror:將getaddrinfo失敗的錯誤碼轉換成錯誤消息
#include <netdb.h>

const char *gai_strerror(int error);

    -- '指向描述錯誤的字符串的指針'
getnameinfo: 套接字地址(addr)被翻譯成一個主機名和一個服務器名映射到一個地址
#include <sys/socket.h>
#include <netdb.h>

int getnameinfo(const struct sockaddr *restrict addr, socklen_t alen, char *restict host, socklen_t hostlen, char *restict service, socklen_t servlen, int flags );

    -- '成功:0;出錯:非0錯誤碼'
  • 參數:函數

    • socklen_t:addr所指向的地址結構體的字節長度。
    • flags
標誌 描述
NI_DGRAM 服務基於數據報而非基於流
NI_NAMEREQD 若是找不到主機名,將其做爲一個錯誤對待
NI_NOFQDN 對於本地主機,僅返回全限定域名的節點名部分
NI_NUMERICHOST 返回主機地址的數字形式,而非主機名
NI_NUMRICSCOPE 對於IPv6,返回範圍ID的數字形式,而非名字
NI_NUMERICSERV 返回服務地址的數字形式(即端口號),而非名字

套接字域地址關聯

關聯服務器地址和套接字
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr ,socklen_t len);

    -- '成功:0;錯誤:-1'
  • 參數:

    • socklen_t:addr所指向的地址結構體的字節長度。
獲取套接字的綁定地址
#include <sys/socket.h>

int getsockename(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp);
    
        -- '成功:0;出錯:-1'
  • 參數:

    • addr:返回的地址緩衝區
    • alenp:返回的地址長度。若是長度不匹配,地址自動階段而不報錯。
獲取對方的地址
#include <sys/socket.h>

int getpeername(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict alenp);
    
        -- '成功:0;出錯:-1'
  • 參數:

    • addr:返回的地址緩衝區
    • alenp:返回的地址長度。若是長度不匹配,地址自動階段而不報錯。

客戶端

鏈接
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t len);

    -- '成功:0;出錯:-1'
  • 參數:

    • socklen_t:addr所指向的地址結構體的字節長度。

服務器

監聽
#include <sys/socket.h>

int listen(int sockfd, int backlog);

    -- '成功:0;出錯:-1'
  • 參數:

    • backlog:提示系統該進程所要入隊的未處理的鏈接請求書。由 <sys/socket.h>中的SOMAXCONN指定上限
      • 隊列滿,系統會拒絕多餘的鏈接請求。
得到客戶端請求並創建鏈接
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *restrict addr, socklen_t *restrict len);

        -- '成功:文件(套接字)描述符;出錯:-1'
  • 參數:

    • socklen_t:addr所指向的地址結構體的字節長度。
  • 特色:

    • 返回的文件描述符是套接字描述符,和原始套接字(sockfd)具備相同的套接字類型和地址族。
    • 阻塞直到得到客戶端請求並創建鏈接,若是sockfd處於非阻塞模式,accept會返回-1,並將errno=EAGEAIN。
    • 可使用poll或select來等待一個請求到來。

數據傳輸:指定選項、從多個客戶端接受數據包、發送外帶數據

發送:
#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags );


    -- '成功:放回發送的字節數;出錯:-1'
  • 參數:

    • flags
標誌 描述
MSG_CONFIRM 提供鏈路層有效以保持地址映射有效
MSG_DONTROUTE 勿將數據包路由出本地網絡
MSG_DONTWAIT 容許非阻塞操做(等價於使用O_NONBLOCK)
MSG_EOF 發送數據後關閉套接字的發送端
MSG_EOR 若是協議支持,標記記錄結束
MSG_MORE 延遲發送數據包容許寫更多數據
MSG_NOSIGNAL 寫無鏈接的套接字時不產生SIGPIPE信號
MSG_OOB 若是協議支持,發送帶外數據
  • 特色:

    • send成功返回,只能保證無錯誤的發送到網絡驅動程序上。並不能保證另外一端進程就必定接受了數據
    • 經過指定標誌來改變處理傳送函數的方式
#include <sys/socket.h>

ssize_t sendto(inft sockfd, const void *buf ,size_t nbytes, int flags, const struct sockaddr *destaddr, socklen_t destlen);

        -- '成功:發送的字節數;出錯:-1'
  • 特色:sendto能夠在無鏈接的套接字上指定一個目標地址。
#include <sys/socket.h>

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

    -- '成功:發送的字節數;出錯:-1'
    
struct iovec {
    iov_base;   //buffer的起始位置
    iov_len;    //buffer的長度
}
struct msghdr {
    void *msg_name;             /*optional addrss */
    socklen_t *msg_name;        /* address size in bytes */
    struct iovec *msg_iov;      /* iovec buffer 指針*/
    int  msg_iovlen;            /* buffer數組長度*/
    void *msg_control;          /* ancillary data */
    socklen msg_controllen;     /* number of ancillary bytes */
    int  *msg_flags;            /* flags for reveived message */
    ...
}
  • 特色:

    • 調用帶有msghdr結構的sengmsg來指定多重緩衝區數據,和writev函數類似。
接受
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags);


    -- '成功:返回數據的字節長度;若無可用數據或對等方已經按序結束,返回0;出錯:-1'
  • 參數:

    • flags:
標誌 描述
MSG_CMSG_CLOEXEC 爲UNIX域套接字上接受的文件描述符社會資執行時關閉標誌
MSG_DONTWAIT 容許非阻塞操做(等價於使用O_NONBLOCK)
MSG_ERRQUEUE 接受錯誤信息做爲輔助數據
MSG_OOB 若是協議支持,獲取外帶數據
MSG_PEEK 返回數據包內容而不真正取走數據包
MSG_TRUNCL 及時數據包唄截斷,也返回數據包的實際長度
MSG_WAITALL 如等待知道直到全部的數據可用(僅SOCK_STREAM)
  • 特色: recv能夠指定標誌來控制如何接受數據。
#include <sys/socket.h>

ssize_t recvfrom(int sockfd, void *restrict buf, size_t len, int flags, struct sockaddr *restrict addr, socklen_t *restrict addrlen);

    -- '成功:返回數據的字節長度;若無可用數據或對等方已經按序結束,返回0;出錯:-1'
#include <sys/socket.h>

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

    -- '成功:返回數據的字節長度;若無可用數據或對等方已經按序結束,返回0;出錯:-1'
  • 參數:

    • flags:
標誌 描述
MSG_CTRUNC 控制數據唄截斷
MSG_EOR 接受記錄結束符
MSG_ERRQUEUE 接受錯誤信息做爲輔助數據
MSG_OOB 若是協議支持,獲取外帶數據
MSG_TRUNCL 通常數據被截斷

套接字選項

  • 通用選項,工做在全部套接字
  • 套接字層次管理的選項,可是依賴於下層協議的支持。
  • 特定於某協議的選項,每一個協議獨有的。
設置
#include <sys/socket.h>

int setsockopt(int sockfd, int level, int option, const void *val, socklen_t len);

    -- '成功:0;出錯:-1
  • 參數:

    • level: 表示了選項應用的協議。
      • 若是通用套接字:level = SOL_SOCKET
      • **若是TCP:level = IPPROTO_TCP **
      • **若是TCP:level = 協議編號 **
    • option: 表示了選項應用的協議。
option 參數val的類型 描述
SO_ACCEPTIONN int 返回信息指示該套接字是否被監聽
SO_BROADCAST int 若是*val非0;廣播數據報
SO_DEBUG int 若是*val非0;啓動過網絡驅動調試功能
SO_DONTROUTE int 若是*val非0;繞過一般路由
SO_ERROR int 返回掛起的套接字錯誤並清除
SO_KEEPALIVE int 若是*val非0;啓用週期性keep-alive報文
SO_LINGER struct linger 當還有未發報文而套接字已關閉,延遲時間
SO_OOBINLINE int 若是*val非0;將帶外數據放到普通數據中
SO_RCVBUF int 接受緩衝區的字節長度
SO_RCVLOWAT int 接受調用中返回的最小數據字節數
SO_RCVTIMEO struct timeval 套接字接受調用的超時值
SO_REUSEADDR int 若是*val非0;重用bind中的地址
SO_SNDBUF int 發送緩衝區的字節長度
SO_SNDLOWAT int 發送調用中傳送的最小數據字節數
SO_SNDTIMEO struct timeval 套接字發送調用的超時值
SO_TYPE int 標識套接字類型
獲取套接字選項
#include <sys/socket.h>

int getsockopt(int sockfd, int level, int option , void *restrict val, socklen_t *restrict lenp);

    -- '成功:0;出錯:-1'

帶外數據

判斷是否已經到達緊急標記
#include <sys/socket.H>

int sockatmark(int sockfd);

        --'成功:若在標記處,返回1;若妹子啊標記處,返回0;出錯:-1'
相關文章
相關標籤/搜索