linux學習筆記之套接字

 

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";

 

 三

相關文章
相關標籤/搜索