Socket学习笔记之二(常用基本函数)

简介:

函数:
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模型的时候再仔细研究。

目录
相关文章
|
3月前
socket编程之回声服务器函数的陷阱
由connect函数使用不当导致的小错误 话不多说先看代码:
25 0
|
3月前
socket编程之 connect()函数
再讲了服务器端的函数调用之后,终于来到了我们的客户端编程了(read/write之后会详细介绍的),客户端编程相较于服务器端来说是非常简单的了,在掌握了服务器端编程之后再看客户端编程就会胸有成竹(只需要在学一个函数即可)。
30 0
|
3月前
socket编程之 accept函数的理解
在进入我们的正题之前,再来复习一波编写服务器的函数流程吧
38 0
|
3月前
|
网络协议 Linux 定位技术
网络编程函数小总结与初识socket
总结服务器端的函数和客户端的函数 再次声明博主写的都是对于linux下的网络编程,没有写关于Windows的网络编程,也许以后会写到。 这里只是总结一下,具体参数的含义等后面的跟新
26 0
|
8月前
|
前端开发
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之socket发送文本状态2
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之socket发送文本状态2
31 0
|
8月前
|
前端开发
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之自定义指令创建之2
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之自定义指令创建之2
32 0
|
8月前
|
JavaScript 前端开发
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之原生dom导入和移除的技巧2
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之原生dom导入和移除的技巧2
24 0
|
4月前
|
网络协议
socket编程函数
socket编程函数
18 0
|
8月前
|
前端开发
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之创建客户端和socket链接1
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之创建客户端和socket链接1
38 0
|
8月前
|
前端开发
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之响应式和视图数据渲染1
前端学习笔记202305学习笔记第二十九天-Socket.io文本编辑实时共享之响应式和视图数据渲染1
31 1