linux的套接字部分比较容易混乱,在这里稍微总结一下。

地址转换函数在地址的文本表达式和它们存放在套接字地址结构中的二进制值进行转换。

地址转换函数有四个:其中inet_addr 和 inet_ntoa适用于IPv4,inet_pton 和 inet_ntop同时适于用IPv4和IPv6。

  • 套接字地址结构分为IPv4套接字地址结构sockaddr_in和IPv6套接字地址结构sockaddr_in6。其中IPv4的套接字地址结构如下。

    • IPv4套接字地址结构:(定义在<netinet/in.h>头文件中)

       struct in_addr{
      in_addr_t s_addr; //
      }; struct sockaddr_in{
      uint8_t sin_len;
      sa_family_t sin_family; //套接字地址结构的地址族
      in_port_t sin_port //TCP或UDP端口,一般为uint16_t
      struct in_addr sin_addr; //IPv4地址,一般为uint32_t
      char sin_zero[];
      };
      • 说明:POSIX规范只需要这个结构中的3个字段:sin_family、sin_addr和sin_port。对于符合POSIX的实现来说,定义额外的结构字段是可以接受的。几乎所有的实现都增加了sin_zero字段,所以所有的套接字地址结构大小都至少是16字节。

      • IPv4地址和TCP或UDP端口号在套接字地址结构中总是以网络字节序来存储,在使用这些字段时,必须要牢记这一点。
      • 32位IPv4地址存在两种不同的访问方法。例如:如果serv第一位某个网际套接字地址结构,那么serv.sin_addr将按in_addr结构引用其中的32位IPv4地址,而serv.sin_addr.s_addr将按in_addr_t(通常是一个uint32_t)引用同一个32位Ipv4地址。在将它作为函数的参数时要注意使用正确的IPv4地址,因为编译器对传递结构和传递正数的处理是完全不同的。
      • sin_zero字段未曾使用,不过在填写这种套接字地址结构时,总是把该字段置为0(总是在填写前把整个结构置为0)
      • 套接字地址结构仅在给定主机上使用:虽然结构中的某些字段(例如IP地址和端口号)用在不同主机之间的通信,但是结构本身并不在主机之间传递。
  • 通用套接字地址结构:
    • 当作为一个参数传递进任何套接字函数时,套接字地址结构总是以引用形式(也就是以指向该结构的指针)来传递。然而以这样的指针作为参数之一的任何套接字函数必须处理来自所有支持的任何协议族的套接字地址结构。在如何声明所传递指针的数据类型上存在一个问题,有了ANSI C后解决办法:void *。然而在ANSI C之前的解决办法是在<sys/socket.h>中定义一个通用的套接字地址结构:

       struct sockaddr{
      uint8_t sa_len;
      sa_family_t sa_family;
      char sa_data[];
      };

      于是套接字函数被定义为以指向某个通用套接字地址结构的一个指针作为其参数之一,例如bind函数的ANSI C函数原型:

      int bind(int, struct sockaddr *, socklen_t);    //一般是uint32_t

      这就要求对这些函数的任何调用都必须要将指向特定于协议的套接字地址结构的指针进行强制类型转换,变成指向某个通用套接字地址类型的指针,如:

      struct sockaddr_in serv;
      
      bind(sockfd, (struct sockaddr *) &serv, sizeof(serv));
  • 值--结果参数
    • 当向一个套接字函数传递一个套接字地址结构时,该结构总是以引用形式来传递,也就是说传递的是一个指向该结构的一个指针。该结构的长度也作为一个参数来传递,但是其传递方式取决于该结构的传递方向:进程-->内核,内核-->进程

      • 从进程到内核传递套接字地址结构的函数有3个:bind,connect,sendto。这些函数的一个参数是指向某个套接字地址结构的指针,另一个参数是该结构的整数大小,例如:

        struct sockaddr_in serv;
        
        connect(sockdf, (SA *) &serv, sizof(serv));
      • 从内核到进程传递套接字地址结构的函数有4个:accept, recvfrom,getsockname和getpeername。这4个函数的其中两个参数是指向某个套接字地址结构的指针和指向表示该结构大小的整数的指针,如:
        struct sockaddr_un cli;
        socklen_t len; len = sizeof(cli);
        getpeername(unixfd, (SA *) &cli, &len);
    • 把套接字地址结构大小这个参数从一个整数改为指向某个整数变量的指针,其原因在于:当单数被调用时,结构大小是一个值,它告诉内核结构的大小,这样内核在写该结构时不至于越界;当函数返回时,结构大小又是一个结果,它告诉进程内核在该结构中究竟存储了多少信息。这种类型的参数成为值-结果参数。
  • 网络字节序 <--> 主机字节序:有四个函数用于网络字节序和主机字节序之间的转换:
    • 以下两个均返回网络字节序
    • uint16_t htons(uint16_t host16bitvalue);
    • uint32_t htonl(uint32_t host32bitvalue);
    • 以下两个均返回主机字节序
    • uint16_t ntohs(uint16_t net16bitvalue);
    • uint32_t ntohs(uint32_t net32bitvalue);
  • 地址转换函数(两组):
    • inet_aton, inet_addr, inet_ntoa:这一组函数在点分十进制字符串("206.168.112.96")与它长度为32位的网络字节序二进制值间转换IPv4地址。原型如下:

      #include <arpa/inet.h>
      
      int inet_aton(const char *strptr, struct in_addr *addrptr);    //返回:若字符串有效则为1,否则为0
      
      in_addr_t inet_addr(const char *strptr);                       //返回:若字符串有效则为32位二进制网络字节序的IPv4地址,否则为INADDR_NONE
      
      char *inet_ntoa(struct in_addr inaddr);              //返回:指向一个点分十进制数串的指针
      
      //还有一个名为inet_network的函数和inet_addr类似,但是其返回的是主机字节序
      in_addr_t inet_network(const char *strptr);

      inet_aton 和 inet_addr 两个函数都是将一个点分十进制字符串转换成一个32位的网络字节序二进制值。inet_aton函数,如果addrptr指针为空,那么该函数仍然对输入的字符串执行有效性检查,但是不存储任何结果。inet_addr函数存在一些问题:所有2^32个可能的二进制值都是有效的ip地址(0.0.0.0-255.255.255.255),但是当出错时函数返回INADDR_NONE常量(通常是一个32位均为1的值),这意味着点分十进制数串255.255.255.255不能由该函数处理,因为它的二进制用来指示该函数失败,inet_addr还存在一个潜在的问题:一些手册声明该函数出错时返回-1而不是INADDR_NONE,这样在对该函数的返回值和一个负常量进行比较时可能会发生问题。如今,inet_addr已经废弃,新的代码应该改用inet_ato函数,更好的解决方法是使用inet_pton函数。另外需要注意的是inet_ntoa函数的参数是in_addr的结构体而不是指针。

    • inet_pton,inet_ntop这一组函数对IPv4和IPv6地址都适用。原型如下:
      #include <arpa/inet.h>
      
      int inet_pton(int family, const char *strptr, void *addrptr);                //返回:若成功则为1,若输入不是有效的表达格式则为0,若出错则为-1
      
      const char *inet_ntop(int family, void *addrptr, char *strptr, size_t len);  //返回:若成功则为指向结果的指针,若出错则为NULL
      //len:INET_ADDRSTRLEN INET6_ADDRSTRLEN
      //inet_ntop函数的strptr不可以是一个空指针,调用者必须为目标存储单元分配内存并制定其大小,调用成功时,这个指针就是该函数的返回值
    • 地址转换函数小结:
                                inet_pton(AF_INET),inet_aton, inet_addr
      点分十进制数 -----------------------------------------------------> in_addr{}
      IPv4地址 <----------------------------------------------------- 32位二进制IPv4地址
      inet_ntop(AF_INET),inet_ntoa
      #include <stdio.h>
      #include <string.h>
      #include <arpa/inet.h> int main(int argc, char **argv)
      {
      const char *ip_str = "127.0.0.1";
      char *ip_res;
      in_addr_t addr_t;
      struct in_addr addr; //1.str -> binary
      inet_aton(ip_str, &addr);
      printf("inet_aton::%x\n", addr); //1000007f addr_t = inet_addr(ip_str);
      printf("inet_addr::%x\n", addr_t); //1000007f inet_pton(AF_INET, ip_str, (void *)&addr); //1000007f
      printf("inet_pton::%x\n", addr); //2.binary -> str
      ip_res = inet_ntoa(addr);
      printf("inet_ntoa::%s\n", ip_res); //127.0.0.1 inet_ntop(AF_INET, &addr, ip_res, INET_ADDRSTRLEN);
      printf("inet_ntop::%s\n", ip_res); //127.0.0.1 return ;
      } output:
      inet_aton::100007f
      inet_addr::100007f
      inet_pton::100007f
      inet_ntoa::127.0.0.1
      inet_ntop::127.0.0.1

ip(点分十进制 <==> 二进制整数)之间的转换的更多相关文章

  1. C# IP地址与整数之间的转换

    IP地址与整数之间的转换 1.IP地址转换为整数 原理:IP地址每段可以看成是8位无符号整数即0-255,把每段拆分成一个二进制形式组合起来,然后把这个二进制数转变成一个无符号的32位整数. 举例:一 ...

  2. [Swift]二进制、八进制、十进制、十六进制之间的转换

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  3. Python—IP地址与整数之间的转换

    1. 将整数转换成IP: 思路:将整数转换成无符号32位的二进制,再8位进行分割,每8位转换成十进制即可. 方法一:#!usr/bin/python 2 #encoding=utf-8 3 #1. 将 ...

  4. Swift_ios_二进制,十进制,十六进制之间的转换

    这里所说的转换,并不是Swift中字面量之间的转换.如果是字面量之间的转换,ios系统中已经自动帮我们转换了. 例如let number1:Int = 8let number2:Int = 0b100 ...

  5. C语言中的字符和整数之间的转换

    首先对照ascal表,查找字符和整数之间的规律: ascall 控制字符  48  0  49  1  50  2  51  3  52  4  53  5  54  6  55  7  56  8 ...

  6. 【PHP】php实现二进制、八进制、十进制、十六进制之间各自转换的函数

    <?php /* 常见的进制: 二进制 binary -----> bin 八进制 octal -----> oct 十进制 decimal -----> dec 十六进制 h ...

  7. IP地址字符串与int整数之间的无损转化

    今天鹅厂店面,最后问了一个ip地址字符串和整数间无损转化的问题,晚上有时间了手撸了一下代码. public class IPstr { public static void main(String a ...

  8. cpp二进制与整数之间的转换的几种方式记录

    PS: 程序为cpp代码,最重要理解操作. 方法一: n进制方法,也可以解决转换为其他进制问题. /*将整数转化为二进制的string 输出*/ string convert(int num) { s ...

  9. 我的Java开发学习之旅------>二进制、八进制、十进制、十六进制之间转换

    一. 十进制与二进制之间的转换  (1) 十进制转换为二进制,分为整数部分和小数部分  ① 整数部分  方法:除2取余法,即每次将整数部分除以2,余数为该位权上的数,而商继续除以2,余数又为上一个位权 ...

随机推荐

  1. 四、spring中高级装配(2)

    这个是接着上一篇写的,这章内容较多,分开来记录一下... 三.处理自动装配的歧义性 自动装配让spring完全负责bean引用注入到构造参数和属性中,不过,仅有一个bean匹配所需的结果时,自动装配才 ...

  2. 制作framework&静态库

    http://blog.csdn.net/justinjing0612/article/details/7880712     (制作framework) http://blog.sina.com.c ...

  3. 树莓派-3 启用root

    默认是user: pi,  password: raspberry 通过如下设置root密码并启用 pi@raspberrypi:~ $ sudo passwd root Enter new UNIX ...

  4. ORM之单表增删改查

    ORM之单表增删改查 在函数前,先导入要操作的数据库表模块,model from model所在的路径文件夹 import model   在views文件中,加的路径: #就一个app01功能的文件 ...

  5. JAVA IO中read()方法的返回值

    read()方法的作用是从输入流读取数据的下一个字节,返回的字节的值是一个0~255之间的整数.到达流的末尾返回-1. 刚开始我以为这个返回值表示的是所读取的数据的长度,可是之后在一个示例程序中发现这 ...

  6. BNUOJ 3226 Godfather

    Godfather Time Limit: 2000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID:  ...

  7. BNUOJ 7697 Information Disturbing

    Information Disturbing Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on HDU. ...

  8. CALayer之 customizing timing of an animation

    customizing timing of an animation Timing is an important part of animations, and with Core Animatio ...

  9. codevs——1039 数的划分

    1039 数的划分 2001年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 将整数 ...

  10. 02-js变量学习

    <html> <head> <title>js的变量学习</title> <meta charset="UTF-8"/> ...