zoukankan      html  css  js  c++  java
  • Unix socket的准备(一)

    套接字地址结构

    套接字编程中,五元组是广为人知的. (host_ip, host_port, target_ip, target_port, protocol).
    其中 ipport 就是由套接字地址结构来表示的, 无论是Server端监听的 ipport 或是客户端连接的服务端的地址,都需要通过套接字地址结构来表示

    ipv4 套接字结构

    # <netinet/in.h>
    
    struct in_addr{            /* Network byte order*/
        in_addr_t   s_addr;    /* 32-bit IPV4 address*/
    };
    
    struct sockaddr_in{
        uint8_t         sin_len;
        sa_family_t     sin_family;     /* Address family, default: AF_INET */
        in_port_t       sin_port;       /* 16 bit port num: Network byte order */
        struct in_addr  sin_addr;       /* 32 bit ip addr: network byte order */
        char            sin_zero[8];    /* Unused */
    };
    

    在Linux的套接字结构中并没有sin_len 成员. POSIX规范中也不要求有这个成员. POSIX规范只需要这个结构中的3个字段 sin_family, sin_addr, sin_port. 几乎所有的实现都增加了sin_zero成员.

    其中sin_port成员和sin_addr成员是网络字节序,需要使用字节排序函数处理。

    通用套接字地址结构

    将套接字结构(ipv4/ipv6/unix sock)传递给内核时需要转成通用的套接字地址结构。

    struct sockaddr{
        uint8_t     sa_len;
        sa_family_t sa_family;
        char        sa_data[14];
    };
    

    值-结果参数

    从内核到进程传递套接字地址结构的函数有4个: acceptrecvfromgetsocknamegetpeername
    这4个函数中的两个参数都是指向某个套接字地址结构的指针和表示该结构大小的整形变量的指针

    struct sockaddr_un cli;  /* Unix domain*/
    socklen_t len = sizeof(cli);
    
    getpeername(unixfd, (sockaddr*) &cli, &len); /* len may have changed*/
    

    这里使用的是len的指针,而不是len,原因在于:当函数被调用时,结构大小是一个值(value),它告诉内核该结构的大小,这样内核在写该结构时不至于越界;当信息返回时,结构大小又是一个结果(result),它告诉进程内核在该结构中究竟存了多少信息.这种类型的参数称为 值-结果(value-result)参数.

    值-结果参数从内核中获取数据的调用中经常会用到. 在网络编程中除了从内核中获取套接字地址的调用外,下面的函数同样也使用了值-结果参数

    select 函数中间的3个参数
    getsockopot函数的长度参数
    使用recvmsg函数, msghdr结构中的msg_namelenmsg_controllen字段
    ifconfifc_len字段
    sysctl 函数两个长度参数中的一个


    字节排序函数

    在网络通信中统一使用大端字节序(即网络字节序)
    在套接字地址结构中, 以sockaddr_in 为例, sin_portsin_addr存储的port和ip均为网络字节序,
    那么对于端口号为8080的端口来说,需要将8080转为网络字节序,才能放到套接字地址结构中。为此我们有字节序转换函数:

    #include <netinet/in.h>
    
    uint16_t htons(uint16_t host16bitvalue);  // 返回:网络字节序
    uint32_t htonl(uint32_t host32bitvalue);
    
    uint16_t ntohs(uint16_t net16bitvalue);
    uint16_t ntohl(uint16_t net32bitvalue);  // 返回:主机的字节序
    

    我们并不关心主机字节序和网络字节序的真实值,我们需要做的调用上述函数在套接字地址结构中存入转后的值就可以。
    在那些主机为大端字节序的机器中,四个函数通常被定义为空宏。

  • 相关阅读:
    iaas,paas,saas理解
    July 06th. 2018, Week 27th. Friday
    July 05th. 2018, Week 27th. Thursday
    July 04th. 2018, Week 27th. Wednesday
    July 03rd. 2018, Week 27th. Tuesday
    July 02nd. 2018, Week 27th. Monday
    July 01st. 2018, Week 27th. Sunday
    June 30th. 2018, Week 26th. Saturday
    June 29th. 2018, Week 26th. Friday
    June 28th. 2018, Week 26th. Thursday
  • 原文地址:https://www.cnblogs.com/pluviophile/p/unp-1.html
Copyright © 2011-2022 走看看