Unix网络编程——常见辅助函数总结

主要总结:网络编程接口中网络字节序与主机字节序的转换、主机信息与套接字信息的解析、点分十进制字符串与十进制整数的转换等。

网络字节序与主机字节序的转换函数:

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

主机信息获取函数:

getsockname

#include <sys/socket.h>
int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// 成功返回0,失败返回-1

getsockname解释:获取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,失败返回-1

getpeername的常见错误:
- 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;
}

点分十进制与整数的转换:

#include<arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);
// 将strptr指向的C字符串转换成一个32位的网络字节序二进制值,存放到addrptr中,成功返回1,失败返回0.
in_addr_t inet_addr(const char *strptr);
// 功能与inet_aton一致,成功返回一个有效的十进制数,失败返回INADDR_NONE(通常是0XFFFFFFFF),这意味着255.255.255.255不能使用该函数进行转换
char *inet_ntoa(struct in_addr inaddr);
// 作用与上面2个函数相反,但是其返回的char*所指向的内存是一个静态内存,因此该函数不可重入

int inet_pton(int af, const char *src, void *dst);
// 成功返回0,失败返回-1.
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);
// 成功返回指向结果的指针(结果存放在dst中),失败返回NULL

在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_errno

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结构体的指针

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值