前言
本章开始介绍API。其中有很多个参数实现的功能差不多,我们除了学习他们的功能之外,要还特别关注形如“有了read为什么还要有readn、readline呢?”之类的问题。下面一一归纳。
关注点
- 套接字地址结构
- 值-结果参数
- 字节排序函数(大小端存储问题)
- 字节操纵函数
- inet_pton inet_ntop函数
- sock_ntop函数
- readn writen和readline函数
套接字地址结构(IPV4地址结构)
struct in_addr{
in_addr_t s_addr;
};
struct sockaddr_in {
uint8_t sin_len;
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
值-结果参数
值:进程到内核
结果:内核到进程
(1)进程到内核传递套接字的地址结构的函数有3个:bind、connect、sendto。如
struct sockaddr_in serv;
/*fill in serv{} */
connect(sockfd, (SA*) &serv, sizeof(serv));
(2)从内核到进程传递套接字地址结构的函数有4个:accept、recvfrom、getsockname和getpeername。通常返回套接字地址结构的长度。
struct sockaddr_un cli; /*Unix domain*/
socklen_t len;
len = sizeof(cli);
getpeername(unixfd, (SA*) &cli, &len);
/* len may have changed */
本书中还会碰到的其他值-结果参数:
- select函数中间的3个参数
- getsockopt函数的长度参数
- 使用recvmsg函数时,msghdr结构中的msg_namelen和msg_controllen字段
- ifconf结构中的ifc_len字段
- sysctl函数两个长度参数中的第一个
字节排序函数(大小端存储问题)
这里不讨论什么是大小端、如何用union判断机器的大小端,而是讨论相应函数的使用。
#include <netinet/in.h>
uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);
uint16_t ntohs(uint16_t net16bitvalue);
uint32_t ntohl(uint32_t net32bitvalue);
网络字节序为大端
而由于历史原因计算机可能大端也可能小端(小端存储居多)
那么需要把主机序转为网络序。
如:
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13);
存储13一个字节就足够所以用htons
而IP地址通常是4个字节所以用htonl
字节操纵函数
#include<string.h>
void bzero(void *dest, size_t nbytes);
void bcopy(const void *src, void *dest, size_t nbytes);
int bcmp(const void *ptrl, const void *ptr2, size_t nbytes);
bzero把目标字节串中指定数目的字节置为0.
bcopy将指定数目的字节从源字节串移到目标字节串
bcmp比较两个任意的字节串,若相同返回0,不同返回非0
#include <string.h>
void *memset(void *dest, int c, size_t len);
void *memcpy(void *dest, const void *src, size_t nbytes);
int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);
memset把目标字符串指定数目的字节置为c
memcpy类似bcopy,不过两个指针参数的顺序相反。当源字节串与目标字节串重叠时,bcopy能够正确处理,但是memcpy的操作结果却不可知。这种情形下必须该用ANSI C的memmove函数。
memcpy比较两个任意的字节串,若相同返回0,否则返回一个非0值。
inet_pton和inet_ntop函数
这个两个函数的作用是实现ip地址点分十进制格式和二进制格式的相互转换。
#include <arpa/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);
//返回:1(成功) 0(不是有效格式) -1(出错)
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
//返回:结果指针(成功) NULL(失败)