zoukankan      html  css  js  c++  java
  • linux IPC socket

    套接字是通讯端点的抽象

    创建一个套接字

    #include <sys/types.h>
    #include <sys/socket.h>
    
    int socket(int domain, int type, int protocol);
    返回值:成功文件(套接字)描述符,失败-1
    domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。 协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。 type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的类型有哪些?)。 protocal:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等 它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

    套接字通信是双向的。可以禁止一个套接字的I/O

    #include <sys/socket.h>
    
    int shutdown(int sockfd, int how);
    返回值:成功0,出错-1
    sockfd:套接字的描述符
    how:三种SHUT_RD(0)关闭sockfd上的读功能
    SHUT_WR(1)关闭sockfd上的写功能
    SHUT_RDWR(2)关闭sockfd的读写功能

    用来在处理器字节序和网络字节序之间实施转换的函数

    #include <arpa/inet.h>
    
    uint32_t htonl(uint32_t hostlong);
    返回值:以网络字节序表示的32位整数 uint16_t htons(uint16_t hostshort);
    返回值:以网络字节序表示的16位整数
    uint32_t ntohl(uint32_t netlong);
    返回值:以主机字节序表示的32位整数
    uint16_t ntohs(uint16_t netshort);
    返回值:以主机字节序表示的16位整数

     h表示主机字节序,n表示网络字节序,l表示长整型,s表示短整型

    打印出能被人理解而不是计算机所理解的地址格式。同时支持IPv4和IPv6地址

    #include <arpa/inet.h>
    
    const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
    返回值:成功地址字符串指针,出错NULL
    af:地址簇,仅支持AF_INET和AF_INET6
    src:来源地址结构指针
    dst:接收转换后的字符串
    size:保存文本字符串的缓冲区大小
    
    int inet_pton(int af, const char *src, void *dst);
    返回值:成功1,格式无效0,出错-1
    af:地址簇,仅支持AF_INET和AF_INET6
    src:转换的地址字符串
    dst:转换后的地址结构指针

    这个很常用,所有使用socket都需要用这两个函数转换,p应该是protocol,n应该是net吧。

    例子

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <sys/types.h>
     4 #include <sys/ioctl.h>
     5 #include <stdlib.h>
     6 #include <netdb.h>
     7 #include <arpa/inet.h>
     8 #include <netinet/in.h>
     9 #include <string.h>
    10 
    11 int main(int argc, char *argv[])
    12 {
    13         char dst[100];
    14         int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    15 
    16         struct sockaddr_in serv;
    17         memset(&serv, 0 ,sizeof(struct sockaddr_in));
    18 
    19         serv.sin_family = AF_INET;
    20         serv.sin_port = htons(5555);
    21 
    22         if((inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr)) == 0)
    23                 printf("inet_pton error
    ");
    24         if((inet_ntop(AF_INET, &serv.sin_addr.s_addr, dst, sizeof(dst))) == NULL)
    25                         printf("inet_ntop error
    ");
    26         printf("dst=%s,sizeof(dst)=%d
    ", dst, sizeof(dst));
    27 
    28         bind(sockfd, (struct sockaddr *)&serv, sizeof(serv));
    29         listen(sockfd, 15);
    30         return 0;
    31 }
    inet_pton

      

    找到给定计算机系统的主机信息

    #include <netdb.h>
    
    struct hostent *gethostent(void);
    返回值:成功返回指针,出错NULL
    
    void sethostent(int stayopen);
    stayopen:true就是TCP,否则UDP
    void endhostent(void);

    能够采用一套相似的接口来获得网络名字和网络编号

    #include <netdb.h>
    
    struct netent *getnetbyaddr(uint32_t net, int type);
    struct netent *getnetbyname(const char *name);
    struct netent *getnetent(void);
    返回值:成功返回指针,出错NULL
    
    void setnetent(int stayopen);
    void endnetent(void);

    在协议名字和协议编号之间进行映射

    #include <netdb.h>
    
    struct protoent *getprottobyname(const char *name);
    struct protoent *getprotobynumber(int proto);
    struct protoent *getprotoent(void);
    返回值:成功返回指针,出错NULL
    
    void setprotoent(int stayopen);
    void endprotoent(void);

    服务是由地址的端口号部分表示的,每个服务由一个唯一的众所周知的端口号来支持。可以使用getservbyname将一个服务名映射到一个端口号,使用函数getservbyport将一个端口号映射到一个服务名,使用函数getservent顺序扫描服务数据库。

    #include <netdb.h>
    
    struct servent *getservbyname(const char *name, const char *proto);
    struct servent *getservbyport(int port, const char *proto);
    struct servent *getservent(void);
    返回值:成功返回指针,出错NULL
    
    void setservent(int stayopen);
    void endservent(void);

    将一个主机和一个服务名映射到一个地址

    #include <sys/socket.h>
    #include <netdb.h>
    
    int getaddrinfo(const char *node, const char *service,
                            const struct addrinfo *hints,
                            struct addrinfo **res);
    返回值:成功0,出错非0错误码
    node:向一个主机名(域名)或者地址串(IPv4的点分十进制串或者IPv6的16进制串)。
    service:指向一个服务名或者10进制端口号数串。
    hints:可以是一个空指针,也可以是一个指向某个addrinfo结构的指针
    res:指向的变量已被填入一个指针,它指向的是由其中的ai_next成员串联起来的addrinfo结构链表
    void freeaddrinfo(struct addrinfo *res);

    addrinfo结构体

    struct addrinfo
    { 
        int ai_flags; 
        int ai_family; //AF_INET,AF_INET6,UNIX etc
        int ai_socktype; //STREAM,DATAGRAM,RAW
        int ai_protocol; //IPPROTO_IP, IPPROTO_IPV4, IPPROTO_IPV6 etc
        size_t ai_addrlen;//length of ai_addr
        char* ai_canonname; //full hostname 
        struct sockaddr* ai_addr; //addr of host
        struct addrinfo* ai_next;
    }

    错误码需要调用函数来转换成错误消息

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    
    const char *gai_strerror(int errcode);

    将一个地址转换成一个额主机名和一个服务名

    #include <sys/socke.h>
    #include <netdb.h>
    
    int getnameinfo(const struct sockaddr *sa, socklen_t salen,
                            char *host, socklen_t hostlen,
                            char *serv, socklen_t servlen, int flags);
    返回值:成功0,出错非0值
    sa:指向包含协议地址的套接口地址结构,它将会被转换成可读的字符串,
    salen:结构的长度,这个结构长度通常由accept、recvfrom、getsockname、getpeername
    host:主机字符串
    hostlen:长度
    serv:服务器字符串
    servlen:长度
    flags:标志位可以有多个用与或

     sockaddr结构体

    struct sockaddr
    {
      unsigned short sa_family;  /*addressfamily,AF_xxx*/
      char sa_data[14];       /*14bytesofprotocoladdress*/
    };

    16-9.c

      1 #include "apue.h"
      2 #if defined(SOLARIS)
      3 #include <netinet/in.h>
      4 #endif
      5 #include <netdb.h>
      6 #include <arpa/inet.h>
      7 #if defined(BSD)
      8 #include <sys/socket.h>
      9 #include <netinet/in.h>
     10 #endif
     11 
     12 void print_family(struct addrinfo *aip)
     13 {
     14     printf(" family ");
     15     switch(aip->ai_family) {
     16     case AF_INET:
     17         printf("inet");
     18         break;
     19     case AF_INET6:
     20         printf("inet6");
     21         break;
     22     case AF_UNIX:
     23         printf("unix");
     24         break;
     25     case AF_UNSPEC:
     26         printf("unspecified");
     27         break;
     28     default:
     29         printf("unknown");
     30     }
     31 }
     32 
     33 void print_type(struct addrinfo *aip)
     34 {
     35     printf(" type ");
     36     switch(aip->ai_socktype) {
     37     case SOCK_STREAM:
     38         printf("stream");
     39         break;
     40     case SOCK_DGRAM:
     41         printf("datagram");
     42         break;
     43     case SOCK_SEQPACKET:
     44         printf("seqpacket");
     45         break;
     46     case SOCK_RAW:
     47         printf("raw");
     48         break;
     49     default:
     50         printf("unknown (%d)", aip->ai_socktype);
     51     }
     52 }
     53 
     54 void print_protocol(struct addrinfo *aip)
     55 {
     56     printf(" protocol ");
     57     switch(aip->ai_protocol) {
     58     case 0:
     59         printf("default");
     60         break;
     61     case IPPROTO_TCP:
     62         printf("TCP");
     63         break;
     64     case IPPROTO_UDP:
     65         printf("UDP");
     66         break;
     67     case IPPROTO_RAW:
     68         printf("raw");
     69         break;
     70     default:
     71         printf("unknown (%d)", aip->ai_protocol);
     72     }
     73 }
     74 
     75 void print_flags(struct addrinfo *aip)
     76 {
     77     printf("flags");
     78     if(aip->ai_flags == 0) {
     79         printf(" 0");
     80     } else {
     81         if(aip->ai_flags & AI_PASSIVE)
     82             printf(" passive");
     83         if(aip->ai_flags & AI_CANONNAME)
     84             printf(" canon");
     85         if(aip->ai_flags & AI_NUMERICHOST)
     86             printf(" numhost");
     87         if(aip->ai_flags & AI_NUMERICSERV)
     88             printf(" numserv");
     89         if(aip->ai_flags & AI_V4MAPPED)
     90             printf(" v4mapped");
     91         if(aip->ai_flags & AI_ALL)
     92             printf(" all");
     93     }
     94 }
     95 
     96 int main(int argc, char *argv[])
     97 {
     98     struct addrinfo *ailist, *aip;
     99     struct addrinfo hint;
    100     struct sockaddr_in *sinp;
    101     const char *addr;
    102     int err;
    103     char abuf[INET_ADDRSTRLEN];
    104 
    105     if(argc != 3)
    106         err_quit("usage: %s nodename service", argv[0]);
    107     hint.ai_flags = AI_CANONNAME;
    108     hint.ai_family = 0;
    109     hint.ai_socktype = 0;
    110     hint.ai_protocol = 0;
    111     hint.ai_addrlen = 0;
    112     hint.ai_canonname = NULL;
    113     hint.ai_addr = NULL;
    114     hint.ai_next = NULL;
    115     if((err = getaddrinfo(argv[1], argv[2], &hint, &ailist)) != 0)
    116         err_quit("getaddrinfo error %s", gai_strerror(err));
    117     for(aip = ailist; aip != NULL; aip = aip->ai_next) {
    118         print_flags(aip);
    119         print_family(aip);
    120         print_type(aip);
    121         print_protocol(aip);
    122         printf("
    	host %s", aip->ai_canonname?aip->ai_canonname:"-");
    123         if(aip->ai_family == AF_INET) {
    124             sinp = (struct sockaddr_in *)aip->ai_addr;
    125             addr = inet_ntop(AF_INET, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
    126             printf(" address %s", addr?addr:"unknown");
    127             printf(" port %d", ntohs(sinp->sin_port));
    128         }
    129         printf("
    ");
    130     }
    131     exit(0);
    132 }
    getaddrinfo
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    通用权限管理设计 之 数据库结构设计
    jQuery LigerUI 插件介绍及使用之ligerDateEditor
    jQuery LigerUI 插件介绍及使用之ligerTree
    jQuery LigerUI V1.01(包括API和全部源码) 发布
    jQuery liger ui ligerGrid 打造通用的分页排序查询表格(提供下载)
    jQuery LigerUI V1.1.5 (包括API和全部源码) 发布
    jQuery LigerUI 使用教程表格篇(1)
    jQuery LigerUI V1.0(包括API和全部源码) 发布
    jQuery LigerUI V1.1.0 (包括API和全部源码) 发布
    nginx keepalived
  • 原文地址:https://www.cnblogs.com/ch122633/p/8074110.html
Copyright © 2011-2022 走看看