函数:
u_long htonl(u_long hostlong)
u_short htons(u_short hostshort)
u_long ntohl(u_long netlong)
u_short ntohs(u_short netshort)
这上面四个函数类似,功能相似,都用来转换数据格式。用来实现处理器中short,long数据类型与网络中的转换。在网络中传输均以字节为单位(除了bit外就是最小的单位了)。一个short占两字节,一个long占四个字节。一个short从一台机子传到另外一台机子上要能够还原,则必须统一规定高低字节顺序。在TCP/IP协议规范中short的高位在低字节,低位在高字节。这与有些处理器中或者系统中表示不一样。例如在windows中:
unsigned short hs = 0x0102;
unsigned short ns = htons( hs );
printf( "0x%04x",ns);//ns:0x0201
所以对于网络端口等数据在使用前必须进行统一,例如
unsigned short port = 2088;
m_sockaddr.sin_port = htons( port );
等等。这四个函数,我开始不知道为什么取这些名字总是记不住,后来想明白了
htons表示host to net short,ntohs表示net to host short
htonl表示host to net long,ntohl表示net to host long
这样不需要刻意去记也就明白了。
unsigned long inet_addr(const char* cp);
char* FAR inet_ntoa(struct in_addr in);
这两个函数用来把表示ip地址的字符串(如:202.114.14.12)跟表示ip的long或者结构之间转换。
inet_addr得到的是已经统一字节顺序的,可以直接赋值给in_addr里的s_adr,例如:
char *pHost = "202.114.14.12"
m_sockaddr.sin_addr.s_addr = inet_addr( pHost );
int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
加载winsock库。返回0表示成功,非0表示错误。第一个参数是版本号,现在最高版本是2.2版,不过Win CE好像只支持1.1版,高位字节表示副版本号,低位字节表示高版本号,所以这里一般就是0x0202或者0x0101或者使用宏定义MAKEWORD(2,2)或者MAKEWORD(1,1),第二个参数是一个与winsock库信息有关的结构,一把不用去管它。在使用winsock前,都必须加载,一般在程序初始化时候做这个事情。一般使用如下:
WSADATA data;
if ( WSAStartup(0x0202,&data) != 0 )
{
printf("error id: %d",GetLastError());
}
上面的GetLastError()是使用非常频繁的函数。很多函数的返回值得意义都是表示函数执行是否出错。当winsock的函数发生错误时,用GetLastError()可以得到最后一次发生错误的错误号。在.Net中有个工具:查找错误,输入错误号,得到错误信息。
int gethostname(char* name,int namelen);
获取主机名。输入参数为缓冲区地址和大小。
struct hostent* FAR gethostbyname(const char* name);
由主机名得到主机信息,可以用来解析域名。需要注意的是MSDN中的一段话“The application must never attempt to modify this structure or to free any of its components. Furthermore, only one copy of this structure is allocated per thread, so the application should copy any information it needs before issuing any other Windows Sockets function calls”这说明了一般用法的时候,要把数据拷贝出来,看看下面代码:
char name[255];
PHOSTENT phostinfo;
PHOSTENT phostinfo1;
WSADATA data;
struct in_addr** addrPtr;
struct in_addr** addrPtr1;
if ( WSAStartup(0x0202,&data) != 0 )
{
printf("error id: %d",GetLastError());
}
if( gethostname ( name, sizeof(name)) == 0)
{
printf("%s",name);
if((phostinfo = gethostbyname(name)) != NULL)
{
for (addrPtr = (struct in_addr **)phostinfo->h_addr_list;*addrPtr;addrPtr++)
{//显示我机子的ip
printf("%s\n", inet_ntoa(**addrPtr));
}
}
else
printf("error id : %d",GetLastError());
}
else
{
printf("error id :%d",GetLastError());
}
if((phostinfo1 = gethostbyname("bbs.whnet.edu.cn")) != NULL)
{
for (addrPtr1 = (struct in_addr **)phostinfo->h_addr_list;*addrPtr1;addrPtr1++)
{//显示bbs.whnet.edu.cn的ip:202.114.0.248
printf("%s\n", inet_ntoa(**addrPtr1));
}
}
else
printf("error id : %d",GetLastError());
for (addrPtr = (struct in_addr **)phostinfo->h_addr_list;*addrPtr;addrPtr++)
{//在这里显示的是bbs.whnet.edu.cn的ip:202.114.0.248,不是我机子的ip
printf("%s\n", inet_ntoa(**addrPtr));
}
struct HOSTENT* FAR gethostbyaddr(const char* addr,int len,int type);
根据ip地址得到主机信息。这里的ip必须是网络字节顺序的。示例代码:
PHOSTENT phostinfo2;
unsigned long ip = inet_addr("127.0.0.1");
if ( (phostinfo2 = gethostbyaddr((char*)&ip,sizeof(ip),AF_INET)) != NULL)
{//显示localhost
printf("host name : %s",phostinfo2->h_name );
}
else
printf("error id : %d",GetLastError());
int getsockname(SOCKET s,struct sockaddr* name,int* namelen);
这个函数用来的得到socket的本地地址,但是前提是socket必须已经bind或者已经是连接上的。如果socket不是面向连接的话,比如udp,那得socket上有数据才行。
int getpeername(SOCKET s,struct sockaddr* name,int* namelen);
这个函数用来得到socket那一边上的地址,显然socket必须得连接上。“The getpeername function can be used only on a connected socket. For datagram sockets, only the name of a peer specified in a previous connect call will be returned—any name specified by a previous sendto call will not be returned by getpeername.”
至于bind,listen,accept,recv,send等后面学select模型的时候再仔细研究。