一、从process到kernel:
bind、connect、sendto三个函数
传给这三个函数的参数是:指向socket address structure的指针、socket address structure的大小(此value告诉内核该结构的大小,使内核在写此结构时不至于越界)
传递这两个参数,是为了确保从process到kernel传递多少data.
socket address structure大小的数据类型应该是 socklen_t
如下所示:
1 struct sockaddr_in_serv; 3 //fill in serv{} 5 connect (sockfd, (SA *) &serv, sizeof(serv));
一、从kernel到process:
accept、recvfrom/getsockname,getpeername,四个函数
传给这三个函数的参数是:指向socket address structure的指针、指向结构体大小的指针(此result告诉进程,内核在此结构中存储了多少信息)
socket address structure大小的数据类型应该是 socklen_t
struct sockaddr_un cli; /* Unix domain */ socklen_t len;len = sizeof(cli); /* len is a value */ getpeername(unixfd, (SA *) &cli, &len); /* len may have changed */
三、Byte Ordering Functions(字节排序函数):
1个2bytes16位的整数,其在内存中存储的方式有两种:
将低序字节存储在起始地址,这称为小端字节序(little-endian)
将高序字节存储在起始地址,这称为大端字节序(big-endian)
主机可能使用上述两种格式的任意一种,我们把主机用的byte ordering称为 host byte order(主机字节序),同时网络协议必须指定一个network byte order(网络字节序),标准规定使用“big-endian(大端)”字节序作为网络字节序。
网络字节序和主机字节序的转换函数如下:
#include <netinet/in.h> uint16_t htons(uint16_t host16bitvalue) ; uint32_t htonl(uint32_t host32bitvalue) ; Both return: value in network byte order(网络字节序值) uint16_t ntohs(uint16_t net16bitvalue) ; uint32_t ntohl(uint32_t net32bitvalue) ; Both return: value in host byte order(主机字节序值)
h代表host
n代表network
s代表short s代表16-bit value(例如TCP或UDP的port number)
l代表long l代表32-bit value(例如IPv4的地址)
三、Byte Manipulation Functions(字节操纵函数):
当我们处理socket address structures时,我们需要字节操作函数,因为我们要对IP地址这样的字段进行操作,它可能含有多个字节的0.
以str开头的函数,用于处理以空字符结束的C字符串。
以字符b开头的函数,如bzerro,bcopy,bcmp
以字符mem开头的函数,如memset,memcpy,memcmp
1 #include <strings.h> 2 void bzero(void *dest, size_t nbytes); //将目标中指定数目的字节置为0,我们经常用此函数来将套接口地址结构初始化为0 3 void bcopy(const void *src, void *dest, size_t nbytes); //将指定数目的字节从源移动到目标 4 int bcmp(const void *ptr1, const void *ptr2, size_t nbytes); //比较任意两个字符串,若是相同返回0,否则返回非0 5 Returns: 0 if equal, nonzero if unequal
1 #include <string.h> 2 void *memset(void *dest, int c, size_t len); //memset将目标中指定数目的字节置为c 3 void *memcpy(void *dest, const void *src, size_t nbytes); //与bcopy相同,但是交换了两个指针参数的顺序,源与目标重叠时,bcopy能正确处理,但是memcopy的操作结果是未知的 4 int memcmp(const void *ptr1, const void *ptr2, size_t nbytes); //比较两个任意字符串,相等返回0,ptr1大于ptr2返回大于0的数,否则返回小于0的数。 5 Returns: 0 if equal, <0 or >0 if unequal (see text)
四、address conversion Functions(字节操纵函数):
用于转换网络地址,从ASCII strings(人们经常用)和network byte ordered binary values(存储在socket address structures中)之间转换。
inet_aton, inet_ntoa, inet_addr 将IPv4地址从 a dotted-decimal string(点分十进制数串) (e.g., “206.168.112.96”) to its 32-bit network byte ordered binary value(网络字节序的二进制值)
. inet_pton , inet_ntop, 处理both IPv4 and IPv6 addresses.
1 #include <arpa/inet.h> 2 int inet_aton(const char *strptr, struct in_addr *addrptr); //将strptr所指的C字符串转换成32位的网络字节序二进制并通过addrptr来存储 3 Returns: 1 if string 是有效的, 0 on error 4 in_addr_t inet_addr(const char *strptr); //不建议使用此函数处理 5 若成功,返回 32-bit binary network byte ordered IPv4 address; 若失败,返回INADDR_NONE INADDA_NONE是一个32位的均为1的值,所以255.255.255.255不能通过此函数处理 6 char *inet_ntoa(struct in_addr inaddr); //将一个32位的网络字节序二进制IPv4地址转换成为点分十进制数串 7 Returns: pointer to dotted-decimal string (返回点分十进制数串)
上面讲的这几个函数都不怎么使用了。
“p” 代表 presentation(表达) ,地址的 presentation格式代表 ASCII string
“n” 代表numeric (数值). 地址的numeric格式代表 用于socket address structure中的二进制值
1 #include <arpa/inet.h> 2 int inet_pton(int family, const char *strptr, void *addrptr); 3 Returns: 1 if OK, 0 if input not a valid presentation format, -1 on error 4 const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len); 5 Returns: pointer to result if OK, NULL on error
对上述两个函数加一层封装:
1 #include "unp.h" 2 char *sock_ntop(const struct sockaddr *sockaddr, socklen_t addrlen); 3 Returns: non-null pointer if OK, NULL on error
sockaddr指向长度为addrlen的套接口地址结构,这个函数使用它自己的static buffer来保存结构,返回值是指向static buffer的指针
陈小洁的三只猫