主要总结:网络编程接口中网络字节序与主机字节序的转换、主机信息与套接字信息的解析、点分十进制字符串与十进制整数的转换等。
getsockname
#include <sys/socket.h>int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);// 成功返回0,失败返回-1getsockname解释:获取sockfd所绑定的地址并存放在addr中,其中addrlen必须初始化,如果addrlen表示的buf不够则结果会被截断后存放在addr中。 常见错误:
EBADF:sockfd非法EFAULT:addr所指向的内存非法EINVAL:addrlen非法ENOBUFS:系统中没有足够的buf来执行操作ENOTSOCK:sockfd并不指向一个真实的套接字描述符getsockname一般使用场景: - 在没有调用bind的TCP客户端,当connect成功返回后,系统会为sockfd分配本地ip和端口号,此时可以通过getsockname来获取系统分配的IP和PORT - 在以端口号0调用bind后,系统会为这个连接分配一个端口,可以通过getsockname来获取分配的端口
getpeername
#include <sys/socket.h>int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);// 成功返回0,失败返回-1getpeername的常见错误: - EBADF: The argument sockfd is not a valid descriptor.(sockfd是非法描述符) - EFAULT:The addr argument points to memory not in a valid part of the PRocess address space.(内存非法) - EINVAL:addrlen is invalid (长度非法). - ENOBUFS:Insufficient resources were available in the system to perform the Operation.(系统资源不足) - ENOTCONN:The socket is not connected.(sockfd不是以建立连接的套接字) - ENOTSOCK:The file descriptor sockfd does not refer to a socket.(sockfd未指向套接字)
getpeername一般使用场景:
当一个套接字服务器的accept获得时,可以通过获取getpeername获取套接字信息获取套接字的地址簇示例:
int sockfd_to_family(int sockfd){ struct sockaddr_in ss; int len = sizeof(ss); if(getsockname(sockfd,(struct sockaddr *)&ss,&len) < 0) return -1; return ss.sin_family;}在IP与点分十进制的转换中,一般使用inet_pton与inet_ntop,inet_aton和inet_addr以及inet_ntoa已经被废弃。而且inet_pton和inet_ntop适用于IPV4和IPV6.
gethostbyname
#include <netdb.h>extern int h_errno;struct hostent *gethostbyname(const char *name);//成功返回非空指针,失败返回NULL,且置h_errnogethostbyaddr
#include <sys/socket.h> /* for AF_INET */#include <netdb.h>extern int h_errno;struct hostent *gethostbyaddr(const void *addr,socklen_t len, int type);//成功返回非空指针,失败返回NULL,且置h_errno。第一个参数,是一个指向struct in_addr结构体的指针struct hostent{ char *h_name; // 官方主机名 char **h_aliases; // 别名 int h_addrtype; // 主机地址类型:AF_INET int h_length; // 地址长度,4byte char **h_addr_list; // 指向IPV4地址的指针数组}// UNP使用示例#include <stdio.h>#include <netdb.h>#include <arpa/inet.h>#include <sys/socket.h>int main(int argc,char **argv){ char *ptr,**PPTr; char str[INET_ADDRSTRLEN]; struct hostent *hptr; struct in_addr * addr; struct sockaddr_in saddr; //取参数 while(--argc>0) { ptr=*++argv; //此时的ptr是ip地址 if(-1 == inet_pton(AF_INET,ptr,&saddr.sin_addr)) //inet_pton()将ptr点分十进制转in_addr { perror("Inet_pton"); continue; } if((hptr=gethostbyaddr((void *)&saddr.sin_addr,4,AF_INET))==NULL) //把主机信息保存在hostent中 { printf("gethostbyaddr error for addr:%s %s/n",ptr,hstrerror(h_errno)); continue; } printf("official hostname: %s/n",hptr->h_name);//正式主机名 for(pptr=hptr->h_aliases;*pptr!=NULL;pptr++)//遍历所有的主机别名 printf("/talias: %s/n",*pptr); switch(hptr->h_addrtype)//判断socket类型 { case AF_INET: //IP类为AF_INET case AF_INET6: //IP类为AF_INET6 pptr=hptr->h_addr_list; //IP地址数组 for(;*pptr!=NULL;pptr++) printf("/taddress: %s/n", inet_ntop(hptr->h_addrtype,*pptr,str,sizeof(str)));//inet_ntop转换为点分十进制 break; default: printf("unknown address type/n"); break; } } return 0;}gethostbyaddr
#include <sys/socket.h> /* for AF_INET */#include <netdb.h>extern int h_errno;struct hostent *gethostbyaddr(const void *addr,socklen_t len, int type);//成功返回非空指针,失败返回NULL,且置h_errno。第一个参数,是一个指向struct in_addr结构体的指针其他类似的域名与IP转换函数: getservbyname,getservbyport,getaddrinfo,freeaddrinfo,gethostbyname_r,gethostbyaddr_r
新闻热点
疑难解答