linux IPC socket

出版圈郭志敏 2017-12-21

套接字是通讯端点的抽象

创建一个套接字

#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);
返回值:成功文件(套接字)描述符,失败-1<br />
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,出错-
sockfd:套接字的描述符
how:三种SHUT_RD()关闭sockfd上的读功能
SHUT_WR()关闭sockfd上的写功能
SHUT_RDWR()关闭sockfd的读写功能

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

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);<br />返回值:以网络字节序表示的32位整数
uint16_t htons(uint16_t hostshort);<br />返回值:以网络字节序表示的16位整数<br />uint32_t ntohl(uint32_t netlong);<br />返回值:以主机字节序表示的32位整数<br />uint16_t ntohs(uint16_t netshort);<br />返回值:以主机字节序表示的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,出错-
af:地址簇,仅支持AF_INET和AF_INET6
src:转换的地址字符串
dst:转换后的地址结构指针

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

#include <netdb.h>

struct hostent *gethostent(void);
返回值:成功返回指针,出错NULL

void sethostent(int stayopen);<br />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错误码

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

sockaddr结构体

struct sockaddr
{
    __SOCKADDR_COMMON (sa_);    /* Common data: address family and length.  协议族*/
    char sa_data[];         /* Address data.  地址+端口号*/
};

相关推荐