套接字相关的数据类型:sockaddr和sockaddr_in;sockaddr用来保存一个套接字,定义如下:
struct sockaddr { unsigned short int sa_family; //指定通信地址类型,如果是TCP/IP通信,则值为AF_inet char sa_data[14]; //最多用14个字符长度,用来保存IP地址和端口信息 };
sockaddr_in的功能与socdaddr相同,也是用来保存一个套接字的信息,不同的是将IP地址与端口分开为不同的成员,定义如下:
struct sockaddr_in { unsigned short int sin_family; //指定通信地址类型 uint16_t sin_port; //套接字使用的端口号 struct in_addr sin_addr; //需要访问的IP地址 unsigned char sin_zero[8]; //未使用的字段,填充为0 };
在这一结构中,in_addr也是一个结构体,定义如下,用于保存一个IP地址:
struct in_addr { uint32_t s_addt; };
用域名取得主机的IP地址:
struct hostent *gethostbyname(const char *name);
结构体hostent的定义如下:
struct hostent { char *h_name;//正式的主机名称 char **h_aliases;//这个主机的别名 int h_addrtype;//主机名的类型 int h_length;//地址的长度 char **h_addr_list;//从域名服务器取得的主机地址 };
用IP地址返回域名:
struct hostent *gethostbyaddr(const void *addr,socklen_t len,int type);
由协议名取的协议数据:
struct protoent *getprotobyname(char *name);
结构体protoent定义如下:
struct protoent { char *p_name;//协议的名称 char **p_aliases;//协议的别名 int p_proto;//协议的序号 };
由协议编号取得协议信息:
struct protoent *getprotobynumber(int proto);
取得系统支持的所有协议:
struct protoent *getprotoent(void);
取得系统支持的网络服务:
struct servent *getservent(void);
结构体servent定义如下:
struct servent { char *s_name;//这个服务的名称 char **s_aliases;//这个服务可能的别名 int s_port;//这个服务可能的端口 char *s_proto;//这个服务可能使用的协议 };
用名称取得系统所支持的服务:
struct servent *getservbyname(char *name,char *proto); //name:服务器名称,proto服务器所使用的协议;
由端口取得服务名称:
struct servent *getservbyport(int port,char *proto) //port是端口的编号,需要注意的是这个端口号需要用htons()函数进行转换,proto表示一个协议的字符串;
将网络地址转换成长整型:
long inet_addr(char *cp); //cp表示一个IP地址字符串;
将长整型IP地址转换成网络地址即大小端模式转换:
char *inet_ntoa(struct in_addr in);
将一个字符串IP地址转换为一个32位的网络序列IP地址:
int inet_aton(const char *string, struct in_addr*addr);
例如:inet_aton("127.0.0.1", &adr_inet.sin_addr)
inet_pton函数原型如下[将"点分十进制" -> "整数"]:
int inet_pton(int af, const char *src, void *dst);
//这个函数转换字符串到网络地址,第一个参数af是地址族,转换后存在dst中
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt); //这个函数转换网络二进制结构到ASCII类型的地址,参数的作用和上面相同,只是多了一个参数socklen_t cnt, //他是所指向缓存区dst的大小,避免溢出,如果缓存区太小无法存储地址的值,则返回一个空指针,并将errno置为ENOSPC
例如:
char IPdotdec[20]; // 存放点分十进制IP地址
struct in_addr s; // IPv4地址结构体 // 输入IP地址 printf("Please input IP address: "); scanf("%s", &IPdotdec); // 转换 inet_pton(AF_INET, IPdotdec, (void *)&s); printf("inet_pton: 0x%x\n", s.s_addr); // 注意得到的字节序 // 反转换 inet_ntop(AF_INET, (void *)&s, IPdotdec, 16); printf("inet_ntop: %s\n", IPdotdec);
将计算机中的32位长整型数转换成网络字符顺序的32位长整型数:
uint32_t htonl(uint32_t hostlong);
例如:servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
将计算机中的16位整型数转换成网络字符顺序的16位整型数:
uint16_t htons(uint16_t hostshort);
例如:servaddr.sin_port = htons(SERV_PORT);
将网络字符顺序的32位长整型数转换成计算机中的32位长整型数:
uint32_t ntohl(uint32_t netlong);
将网络字符顺序的16位整型数转换成计算机中的16位整型数:
uint16_t ntohs(uint16_t netshort);