注明:本文为学习经验的总结,绝大部分引用自Unix网络编程卷一,有错误或者交流意见请发邮件至yb.zhaoyubo@gmail.com.非常感谢
本文简单简单介绍一下关于网络编程中的套接字地址结构的常用函数。
1.字节操作函数
内存中有两种方法存储字节:一种是将低序字节存储在起始位置,称为小端字节序。一种是将高序字节村出来起始位置,称为大端字节序。
网际协议使用大端字节序作为网络字节序来传送这些多字节整数。
以下为主机字节序与网络字节序之间转换的4个函数:
#include
uint16_t htons (uint16_t host16bitvalue);
uint32_t htonl (uint32_t host32bitvalue);
uint16_t ntohs (uint16_t net16bitvalue);
uint32_t ntohl (uint32_t net32bitvalue);
2.字节操纵函数
操纵多字节字段的函数既不对数据做解释也不假设数据是以空字符结尾的C字符串。在初始化套接字地址结构,操纵IP地址等等的情况,我们需要使用这些函数。
源自Berkeley的函数:
#include
void bzero(void *dest,size_t nbytes); //初始化
void bcopy(const void *src,void *dest,size_t nbytes); //把指定长度的字节从src移动到dest处
int bcmp(const void *ptr1, const void *ptr2, size_t nbytes); //比较两个字符串,相等返回0,否则为非0
源自ANSI C的函数:
#include
void* memset(void *dest, int c, size_t len);//初始化
void* memcpy(void* dest, const void *dest, size_t nbytes);
int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);
3.网际地址转换函数
通常人们喜欢用ASCII字符串的点分十进制来表示IP地址,而套接字地址结构中存放的是网络字节序的二进制值。因此我们介绍一组网络地址转换的函数。
只对IPv4地址有效,其中a可代表字符串,n代表二进制数值:
#include
int inet_aton(const char *strptr, struct in_addr *addrptr); //a可以理解成字符串,字符串有效返回1,否则0.
char* inet_ntoa(struct in_addr inaddr);
in_addr_t inet_addr(const char *strptr);
以下两个是随IPv6出现的函数,应尽量使用这两个函数以保证IPv4与IPv6的兼容性。其中p可代表字符串,n代表二进制数值。
#include
int inet_pton(int family, const char *strptr, void *addrptr);
const char* ntop(int family, const void* addrptr, char *strptr, size_t len);
这两个函数的family参数可以为AF_INET或AF_INET6,如果以不被支持的地址族作为参数,则将errno置为EAFNOSUPPORT错误。
第一个函数成功则返回1,输入不是有效的表达式则返回0,出错则返回 -1.
第二个函数必须为strptr分配足够大小的空间以存储返回的地址串,参数len则为分配空间的大小,若分配空间大小不够,则置errno为ENOSPC。若成功则返回指向结构的指针,若出错则为NULL。
4.编写协议无关的函数 sock_ntop
前两个函数中必须在参数family中指定地址族,因此要编写协议无关的代码我们开发一个sock_ntop函数。
函数输入套接字地址结构及长度,在函数体内分配一个静态字符串作为输出。
#include
#include
#include
char* sock_ntop(const struct sockaddr *sa, socklen_t salen){
char portstr[8];
static char str[128];
switch(sa->sa_family){
case AF_INET:
Struct sockaddr_in *sin=(struct scokaddr_in*)sa;
if(inet_ntop(AF_INET,&sin->sin_addr,str,sizeof(str))==NULL)
return NULL;
return str;
case AF_INET6:
Struct sockaddr in *sin=(struct sockaddr_in6)sa;
if(inet_ntop(AF_INET6,&sin->sin6_addr,str,sizeof(str))==NULL)
return NULL;
return str;
}
}