罕用的数据结构及函数

地址转换类

主机字节序与网络字节序的转换

主机序通常为小端,网络字节序为大端。下列函数在<netinet/in.h>包中:

  1. usinged long int htonl(unsigned long int hostlong) —— 主机序转网络序(host to network long)
  2. usinged short int htons(unsigned short int hostlong) —— 主机序转网络序(host to network short)
  3. usinged long int ntohl(unsigned long int hostlong) —— 网络序转主机序(network to host long)
  4. usinged short int ntohl(unsigned short int hostlong) —— 网络序转主机序(network to host short)

IP地址转换函数

计算机可能辨认二进制的IP地址,但生存中咱们罕用点分十进制来示意IPv4地址,用十六进制示意IPv6地址,于是须要一些函数对他们进行一些转换,这些函数位于<arpa/inet.h>包中。

  1. in_addr_t inet_addr(const char* strprt) —— 将点分十进制IPv4地址转化成网络字节序的地址
  2. int inet_aton(const char cp, struct in_addr inp) —— 同上,将后果存在指针里
  3. char* inet_ntoa(struct in_addr in) —— 将二进制后果转为点分十进制
  4. int inet_pton(int af, const char src, void dst) —— 将十六进制地址转为二进制地址,并存在指针。其中af示意地址族,能够是AF_NET或AF_NET6。
  5. const char inet_ntop(int af, const void src, char* dst, socklen_t cnt) —— 将二进制地址转换为十六进制地址,其中cnt指定指标存储单元大小

socket地址构造

通用socket地址——sockaddr

#include <bits/socket.h>struct sockaddr {    sa_family_t sa_family;    char sa_data[14];}

其中,sa_family是地址族,包含:PF_UNIX(UNIX本地区协定族)、PF_INET(TCP/IPv4地址协定族)、PF_INET6(IPv6地址协定族)。留神:AF_xxx和PF_xxx在socket.h中值雷同,因而常混用。
sa_data用于寄存socket地址值,不同协定的地址具备不同含意和长度。PF_UNIX寄存的是文件的路径名(疑难:在PF_UNIX中,socket是以一个什么样的模式存在的?),长度可达到108字节;在PF_INET中,寄存16bit的端口号和32bit的IPv4地址;在AF_INET6中,寄存的是128bit的IPv6地址、16bit端口号以及32bit的ID。
因为14字节显然无奈容下所有地址,因而linux中sockaddr定义为:

#include <bits/socket.h>struct sockaddr {    sa_family_t sa_family;    unsigned long int __ss_align;    char __ss_padding[128-sizeof(__ss_align)];}

linux下各协定的socket地址

  • PF_UNIX的socket地址构造:
#include <sys/un.h>struct sockaddr_un {    sa_family_t sin_family;    char sun_path[108];     //文件路径名}
  • PF_INET的socket地址构造;
struct sockaddr_in {    sa_family_t sin_family;    u_int16_t sin_port;     //端口号    struct in_addr sin_addr;    //IPv4构造体}struct in_addr {    u_int32_t s_addr;}
  • PF_INET6的socket地址构造;
struct sockaddr_in6 {    sa_family_t sin_family;    u_int16_t sin_port;     //端口号    u_int32_t sin6_flowinfo;    //流信息,应设置为0    struct in6_addr sin6_addr;    //IPv4构造体    u_in32_t sin6_scope_id;}struct in_addr {    unsigned char sa_addr[16];}

留神:所有专用socket地址在理论应用时都须要强制转换为通用sockaddr!

socket通信罕用根底函数

创立socket

int socket(int domain, int type, int protocol);
其中domain为底层协定族,即PF_UNIX, AF_INET, AF_NET6;
type为服务类型,次要分为SOCK_STREAM(流服务)和SOCK_UGRAM(数据报服务),TCP面向流,UDP面向数据报。
protocol示意在前两个参数形成的汇合下,再抉择一个具体的协定。但因为这个汇合通常只有一个值,个别状况下protocol都设置为0。
该函数设置胜利时会返回一个socket文件描述符,失败时会返回-1并设置errno
留神:若设置失败,能够应用perror()来打印具体的错误信息

socket命名(绑定)—— 仅服务端应用

int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen);
bind作用是将由socket()创立后的未经调配的文件描述符与一个ip地址绑定。留神:下面提到的须要强制地址转换就是在这里进行。addrlen间接用sizeof即可。

监听socket —— 仅服务端应用

int listen(int sockfd, int backlog)
此处的backlog指所有处于齐全连贯和半连贯状态的客户端socket下限。最多可有backlog+1个socket申请连贯。

接管连贯 —— 仅服务端应用

int accept(int sockfd, struct sockaddr addr, socklen_t addrlen)
该函数作用是从listen()监听的队列中接管一个连贯,接管后返回一个新的连贯socket,服务器可通过读写该socket与客户端进行通信。
留神:对于客户端来说,accept仅仅只是从申请连贯的socket当选一个进去进行连贯,而不论客户端是否放弃连贯

发动连贯 —— 仅客户端应用

int accept(int sockfd, struct sockaddr serv_addr, socklen_t addrlen)

敞开连贯

int close(int fd)