1、
不同类型CPU的计算机存储多字节变量的顺序不同,故主机字节序分为大端序和小端序:
大端序:高位字节存储在内存的低地址。例如网络传输中使用的字节序。
小端序:低位字节存储在内存的低地址。例如Inter和AMD的主机。
如下所示为一个4字节的int分别使用大端序和小端序的存储顺序:
2、
inet_addr()将一个IPV4类型的点分十进制格式IP地址转换为一个32位网络字节序IP地址。函数原型:
unsigned long inet_addr(const char *cp);
htons()将一个unsigned short(端口号)从主机字节序转换为网络字节序。函数原型:
u_short htons(u_short hostshort);
htonl()将一个unsigned long从主机字节序转换为网络字节序。
eg:
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(6000);
connect(sockClient, (SOCKADDR*)&addr, sizeof(SOCKADDR));
inet_ntoa()函数将一个in_addr结构体类型转换为点分十进制格式IP地址。函数原型:
char* inet_ntoa(struct in_addr in);
ntohs()函数将一个unsigned short(端口号)从网络字节序转换为主机字节序。函数原型:
u_short ntohs(u_short netshort);
ntohl()函数将一个unsigned long从网络字节序转换为主机字节序。
eg:
SOCKET sockConnect = accept(sockSrv, (sockaddr*)&addrRemote, &len);
char sendBuf[100];
sprintf(sendBuf, "Welcome %s:%d!", inet_ntoa(addrRemote.sin_addr), ntohs(addrRemote.sin_port));
InetPton()、InetNtop()函数与inet_addr()、inet_ntoa()功能一样,不过增加了对IPV6地址类型的支持。
3、
gethostname():获得主机名。
gethostbyname()函数可以通过主机名获得主机信息,如主机别名、主机地址等。函数原型:
struct hostent* gethostbyname(const char *name);
hostent结构体:
struct hostent {
char *h_name; /* official name of host */ 主机正式名
char **h_aliases; /* alias list */ 主机别名
int h_addrtype; /* host address type */ 主机地址类型
int h_length; /* length of address */ 主机地址长度
char **h_addr_list; /* list of addresses */ 主机地址
}
Windows Sockets 2上不再推荐使用gethostbyname(),而是使用getaddrinfo()。
eg: 使用gethostbyname()
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")
int GetHostInfor()
{
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
int err;
err = WSAStartup(wVersionRequested, &wsaData);//加载套接字库
if(err != 0)
return 1;
if(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1)
{
WSACleanup();
return 1;
}
struct hostent *host;
if((host = gethostbyname("www.google.com")) == NULL)
{
int n = WSAGetLastError();
fprintf(stderr,"获得地址信息失败:%d,%s\n", n,strerror(h_errno));
return 1;
}
fprintf(stdout,"官方主机名:%s\n", host->h_name);
fprintf(stdout,"主机别名:\n");
char **p;
for(p=host->h_aliases; *p!=NULL; p++)
{
fprintf(stdout,"\t\t%s\n", *p);
}
if(host->h_addrtype == AF_INET)
{
fprintf(stdout,"主机地址类型: IPV4\n");
}
else
{
fprintf(stdout,"主机地址类型: IPV6\n");
}
fprintf(stdout,"主机地址长度:%d\n", (host->h_length)*8);
fprintf(stdout,"主机地址:\n");
struct in_addr addr;
for(p=host->h_addr_list; *p!=NULL; p++)
{
addr.s_addr = *(u_long *) *p;
fprintf(stdout,"\t%s\n", inet_ntoa(addr));
}
return 0;
}
输出为:
官方主机名:www.google.com
主机别名:
主机地址类型: IPV4
主机地址长度:32
主机地址:
74.125.128.99
74.125.128.105
74.125.128.147
74.125.128.106
74.125.128.103
74.125.128.104
使用getaddrinfo():
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int GetHostInfor(char* pHostName)
{
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
int err;
err = WSAStartup(wVersionRequested, &wsaData);//加载套接字库
if (err != 0)
return 1;
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
return 1;
}
addrinfo* pAddrInfo;
int iRet = getaddrinfo(pHostName, NULL, NULL, &pAddrInfo);
if (iRet != 0)
{
printf("getaddrinfo() failed:%d\n", iRet);
return -1;
}
addrinfo* ptr = pAddrInfo;
printf("主机地址:\n");
while (ptr)
{
char ipbuf[32] = { 0 };
struct sockaddr_in * addr = (struct sockaddr_in *)ptr->ai_addr;
printf("\t%s\n", inet_ntop(AF_INET, &addr->sin_addr, ipbuf, 16));
ptr = ptr->ai_next;
}
return 0;
}
gethostbyaddr()函数通过主机地址(网络字节序)获得主机信息。函数原型:
struct hostent* gethostbyaddr(const char *addr, int len, int type);
Windows Sockets 2上不再推荐使用gethostbyaddr(),而是使用getnameinfo()函数。
4、
getservbyname()函数获得给定服务名和协议名的相关服务信息。函数原型:
struct servent* getservbyname(const char *name, const char *proto);
servent结构体:
struct servent
{
char *s_name; /* official service name */ 官方服务名
char **s_aliases; /* alias list */ 别名列表
int s_port; /* port number */ 端口号
char *s_proto; /* protocol to use */ 使用协议
}
eg:
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")
int GetServInfor()
{
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
int err;
err = WSAStartup(wVersionRequested, &wsaData);//加载套接字库
if(err != 0)
return 1;
if(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1)
{
WSACleanup();
return 1;
}
struct servent *ser;
if((ser = getservbyname("http", NULL)) != NULL)
{
fprintf(stdout,"官方服务名:%s\n", ser->s_name);
fprintf(stdout,"别名:\n");
char **p;
for(p = ser->s_aliases; *p!=NULL; p++)
{
fprintf(stdout,"\t%s\n", *p);
}
fprintf(stdout,"端口号:%d\n", ntohs(ser->s_port));
fprintf(stdout,"使用协议:%s\n", ser->s_proto);
}
return 0;
}
输出为:
官方服务名:http
别名:
www
www-http
端口号:80
使用协议:tcp
getservbyport()函数获得给定端口号和协议名的相关服务信息。函数原型:
struct servent* getservbyport(int port, const char *proto);