socket

指定期望的通信协议类型

头文件:
    #include <sys/types.h>   
    #include <sys/socket.h>
原型:
    int socket(int domain, int type, int protocol);
参数:
    int domain:Linux支持的协议族(地址族);
        AF_UNIX, AF_LOCAL   Local communication              unix(7)
        AF_INET             IPv4 Internet protocols          ip(7)
        AF_INET6            IPv6 Internet protocols          ipv6(7);
    int type:套接字类型
        SOCK_STREAM:字节流式套接字----> TCP
        SOCK_DGRAM: 数据报式套接字----> UDP
        SOCK_RAW:原始套接字,传输协议需要在第三个参数指定;
    int protocol:传输协议。如果不需要填0;
    IPPROTO_TCP 和 IPPROTO_UDP;
返回值:
    成功,返回套接字的文件描述符;
    失败,返回-1,更新errno;  
例程:
    //TCP
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd < 0)
    {
        perror("socket");
        return -1;
    }
    //UDP
    int sfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sfd < 0)
    {
        perror("socket");
        return -1;
    }
    //UNIX
    int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
    if(sfd < 0)
    {
        perror("socket");
        return -1;
    }
    //UNIX
    int sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if(sfd < 0)
    {
        perror("socket");
        return -1;
    }

地址结构

每个协议族都定义了自己的套接字地址结构,这些结构的名字均以sockaddr_开始,并对应每个协议族为后缀。如IPv4的套接字地址结构体为 sockaddr_in,而IPv6的套接字地址结构为sockaddr_in6。

//通用地址结构体
struct sockaddr {
    unsigned short     sa_family;   /*地址族*/
    char               sa_data[14]; /*14字节的协议地址,包含该socket的IP地址和端口号*/
};

//AF_INET
typedef unsigned short sa_family_t;
typedef uint16_t in_port_t;
struct sockaddr_in {
    sa_family_t        sin_family;  /*AF_INET*/
    in_port_t          sin_port;    /*端口号*/
    struct in_addr     sin_addr;    /*IP地址*/
    unsigned char      sin_zero[8]; /*填充0 以保持与struct sockaddr同样大小*/
};
typedef uint32_t in_addr_t;
struct in_addr {
    in_addr_t          s_addr;      /* 网络字节序形式的IP地址 */
};

//AF_UNIX
#define UNIX_PATH_MAX    108
struct sockaddr_un {
    sa_family_t sun_family;               /* AF_UNIX */
    char        sun_path[UNIX_PATH_MAX];  /* 文件的路径+文件名*/
};

//AF_INET6
typedef unsigned short sa_family_t;
typedef uint16_t in_port_t;
struct sockaddr_in6 {
    sa_family_t     sin6_family;   /* AF_INET6 */
    in_port_t       sin6_port;     /* 端口号 */
    uint32_t        sin6_flowinfo; /* IPv6 flow information */
    struct in6_addr sin6_addr;     /* IPv6地址 */
    uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */
};
struct in6_addr {
    unsigned char   s6_addr[16];   /* 网络字节序形式的IPv6地址*/
};

setsockopt | getsockopt

设置和获取网络属性

头文件:
    #include <sys/types.h>   
    #include <sys/socket.h>
原型:
    int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
    int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
参数:
    int sockfd:要设置、获取属性的套接字;
    int level:指定要控制的套接字的层次;
        1)SOL_SOCKET:API层
        2)IPPROTO_IP: IP层
        3)IPPROTO_TCP:TCP层
        4)IPPROTO_UDP:UDP层
    int optname:指定控制方式:
        SO_BROADCAST:广播
        SO_REUSEADDR:地址快速重用
        SO_SNDBUF:发送缓冲区
        SO_RCVBUF:接收缓冲区  
        SO_RCVTIMEO:接收超时
        SO_SNDTIMEO:发送超时
    void *optval:获取或者设置套接字选项的变量地址,根据指定控制方式的数据类型进行转换;
    socklen_t *optlen:第四个参数指向的参数大小;
返回值:
    成功,返回0;
    失败,返回errno;
例程:
//发送端(客户端)设置开启广播权限
    int value = 1;
    if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&value,sizeof(value)) < 0)
    {
        ERR_LOG("setsockopt");
        return -1;
    }
//端口快速重用
    int reuse = 1;
    if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
    {
        ERR_LOG("setsockopt");
        return -1;
    }
//接收端(服务器)加入多播组
    struct ip_mreq mq;
    mq.imr_multiaddr.s_addr = inet_addr(IP); //组播IP
    mq.imr_interface.s_addr = inet_addr("0.0.0.0"); //本机IP
    if(setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mq, sizeof(mq))<0)
    {
        ERR_LOG("setsockopt");
        return -1;
    }
    printf("----加入多播组成功----\n");
//设置超时时间
struct timeval
{                              
    __time_t tv_sec;        /* Seconds.  */
    __suseconds_t tv_usec;  /* Microseconds.  */
}; 
    struct timeval val = {5, 0};
    setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &val, sizeof(val));//接收超时
    setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, &val, sizeof(val));//发送超时

网络属性参数设置表

Last modification:2021 年 04 月 19 日 19 : 13 : 23