地址族与数据序列 (转)

摘要:
地址系列和数据序列分配给套接字IP的IP地址和端口号是网络协议的缩写,也是分配给计算机用于发送和接收网络数据的值。用于区分套接字的端口号IP用于区分计算机。只要有IP地址,数据就可以传输到目标,但仅这些地址无法传输到最终应用程序。网络字节顺序和地址转换字节顺序和网络字节顺序CPU数据存储方法分为大端和小端。为了分配IP地址,它需要表示为32个整数数据。同时,执行网络字节顺序转换。
地址族与数据序列

分配给套接字的IP地址与端口号

IP是网络协议的简写,为收发网络数据而分配给计算机的值。端口号是为区分程序中创建的套接字而分配给套接字的序号。

网络地址

两种IP地址:

地址族与数据序列 (转)第1张

IPv4和IPv6的主要差别是表示IP地址所用的字节数。

IPv4标准的4字节IP地址分为网络地址和主机地址。且分为ABCD等类型。

地址族与数据序列 (转)第2张

网络地址(网络ID)是为区分网络而设置的一部分IP地址。

传输数据时,并非一开始就浏览所以4字节的IP地址,而是先浏览IP地址中的网络地址,先把数据传到网络。构成网络的路由器接到数据后,浏览传输数据的主机地址并将数据传给目标计算机。

地址族与数据序列 (转)第3张                                                 

所以,向相应网络传输数据实际上是向构成网络的路由器或交换机传递数据,由接受数据的路由器根据数据中的主机地址向目标主机传递数据。

网络地址分类与主机地址边界

只需通过IP地址的第一个字节即可判断网络地址所占用的字节数,根据IP地址的边界区分网络地址:

地址族与数据序列 (转)第4张

正因如此,通过套接字收发数据时,数据传到网络后即可轻松找到正确的主机。

用于区分套接字的端口号

IP用于区分计算机,只要有IP地址就能向目标追击传输数据,但仅凭这些无法传输给最终的应用程序。

计算机中一般配有NIC(网络接口卡)数据传输设备。通过NIC向计算机内部传输数据时会用到IP。操作系统负责把传递到内部的数据适当分配给套接字,就要利用端口号。

通过NIC接受的数据内有端口号,操作系统参考端口号把数据传输给相应端口的套接字:                                      地址族与数据序列 (转)第5张

端口号时同一操作系统内为区分不同套接字而设置的。因此无法将1个端口号分配给不同套接字。

虽然端口号不能重复,但TCP套接字和UDP套接字不会共用端口号,所以允许重复。

如:某TCP套接字使用9190号端口,则其他TCP套接字无法使用该端口号,但UDP套接字可以使用。

总之,数据传输目标地址同时包含IP地址和端口号,只有这样,数据才会被传输到最终的目的应用程序。

地址信息的表示

表示IPv4地址的结构体

  1.  
    struct sockaddr_in
  2.  
    {
  3.  
    sa_family_t family_t; //地址族
  4.  
    uint16_t sin_port; //16位TCP/UDP端口号
  5.  
    struct in_addr sin_addr; //32位IP地址
  6.  
    char sin_zero[8]; //不使用
  7.  
    }
  8.  
     
  9.  
    struct in_addr
  10.  
    {
  11.  
    in_addr_t s_addr; //32位的IPv4地址
  12.  
    }

//参考POSIX中定义的数据类型

地址族与数据序列 (转)第6张

结构体sockaddr_in的成员分析

地址族与数据序列 (转)第7张

sockaddr_in的结构体变量地址值将以如下方式传递给bind函数。

地址族与数据序列 (转)第8张

网络字节序与地址变换

字节序与网络字节序

CPU数据保存方式分为大端和小端。主流CPU以小端序方式保存数据。

分析字节序不同的计算机之间数据传递过程:

地址族与数据序列 (转)第9张

大端序系统传输数据0x1234时,发送顺序为0x12,0x34;    (从保存在地位地址的数据开始传输)

接受端以小端序保存数据,因此接受的数据变为0x3412;

正因如此,在通过网络传输数据时约定统一方式,这种约定成为网络字节序,非常简单---全统一为大端序。

即先把数据数组转化成大端序格式再进行网络传输。

字节序转换

  1.  
    unsigned short htons(unsigned short); //h to n把short型数据从主机字节序转化为网络字节序
  2.  
    unsigned short ntohs(unsigned short); //n to h把short型数据从网络字节序转化为主机字节序
  3.  
    unsigned long htonl(unsigned long); //h to n..long....
  4.  
    unsigned long ntohl(unsigned long); //n to h..long...

htons中的h代表主机(host)字节序

htons中的n代表网络(network)字节序

s代表short,l代表long

通常,以s作为后缀的函数中,s代表2个字节short,因此用于端口号转换;以l作为后缀的函数中,l代表4个字节,因此用于IP地址转换。

例子:以上函数的调用:

  1.  
    //endian.conv.c
  2.  
    #include<stdio.h>
  3.  
    #include<arpa/inet.h>
  4.  
     
  5.  
    int main(int argc, char *argv[])
  6.  
    {
  7.  
    unsigned short host_port = 0x1234;
  8.  
    unsigned short net_port;
  9.  
     
  10.  
    unsigned long host_addr = 0x12345678;
  11.  
    unsigned long net_addr;
  12.  
     
  13.  
    net_port = htons(host_port);
  14.  
    net_addr = htonl(host_addr);
  15.  
     
  16.  
    printf("Host ordered port: %#x ",host_port);
  17.  
    printf("Network ordered port: %#x ",net_port);
  18.  
    printf("Host ordered address: %#lx ",host_addr);
  19.  
    printf("Network ordered address: %#lx ",net_addr);
  20.  
     
  21.  
    return 0;
  22.  
    }

在小端序CPU中运行的结果:

地址族与数据序列 (转)第10张

网络地址的初始化与分配

将字符串信息转换为网络字节序的整型数

sockaddr_in保存地址信息的成员为32位整型。为了分配IP地址,需要将其表示为32为整数型数据。

IP地址的表示是点分十进制表示法(192.168.1.1),函数inet_addr可以将字符串形式的IP地址转换成32位整形地址。并且同时进行网络字节序转换。

inet_addr函数:

地址族与数据序列 (转)第11张

类型in_addr_t在内部声明为32位整数型。

  1.  
    /* inet_addr函数将点分十进制转换为32为整型数据。并且该整型值满足网络字节序 */
  2.  
    #include<stdio.h>
  3.  
    #include<arpa/inet.h>
  4.  
     
  5.  
    int main(int argc,char *argv[])
  6.  
    {
  7.  
    char *addr1 = "1.2.3.4";
  8.  
    char *addr2 = "1.2.3.256"; //256是错误的IP地址,检测该函数的错误检测能力
  9.  
     
  10.  
    unsigned long conv_addr = inet_addr(addr1);
  11.  
    if (conv_addr == INADDR_NONE)
  12.  
    printf("Error! ");
  13.  
    else
  14.  
    printf("Network ordered integer addr: %#lx ",conv_addr);
  15.  
     
  16.  
    conv_addr = inet_addr(addr2);
  17.  
    if(conv_addr == INADDR_NONE)
  18.  
    printf("Error! ");
  19.  
    else
  20.  
    printf("Network ordered integer addr: %#lx ",conv_addr);
  21.  
     
  22.  
    return 0;
  23.  
    }

地址族与数据序列 (转)第12张

inet_aton函数:与inet_addr函数在功能上完全相同,只不过函数利用了in_addr结构体

地址族与数据序列 (转)第13张

inet_ntoa函数:将网络字节序整数IP地址转换成熟悉的字符串(点分十进制形式)

地址族与数据序列 (转)第14张

网络地址初始化

介绍套接字创建过程中常见的网络地址信息初始化方法

  1.  
    struct sockaddr_in addr;
  2.  
    char *serv_ip = "211.217.168.13"; //声明IP地址字符串
  3.  
    char *serv_port = "9190"; //声明端口号字符串
  4.  
    memset(&addr,0,sizeof(addr)); //结构体变量addr的所有成员初始化为0
  5.  
    addr.sin_family = AF_INET; //指定地址族
  6.  
    addr.sin_addr.s_addr = inet_addr(serv_ip); //基于字符串的IP地址初始化
  7.  
    addr.sin_port = htons(atoi(serv_port)); //基于字符串的端口号初始化

memset函数用来初始化addr,每个字节都初始化为同一个值(0);最后一个参数传入addr的长度

客户端地址信息初始化

上述网络地址信息初始化过程主要针对服务器端而非客户端。给套接字分配IP地址和端口号主要为下面的事作准备:

地址族与数据序列 (转)第15张

反观客户端中连接请求如下:

地址族与数据序列 (转)第16张

服务器端的准备工作通过bind函数完成,而客户端则通过connect函数完成。

服务器端声明sockaddr_in结构体变量,将其初始化为赋予服务器端IP和套接字的端口号,然后调用bind函数;

客户端则声明sockaddr_in结构体,并初始化为要与之连接的服务器端套接字的IP和端口号。然后调研connect函数.

INADDR_ANY

利用常数INADDR_ANY分配服务器端的IP地址。这种方式可以自动获取运行服务器端的计算机IP地址,不必亲自输入。

向套接字分配网络地址

bind将初始化后的地址信息分配给套接字。

地址族与数据序列 (转)第17张

服务器端常见套接字初始化过程

  1.  
    int serv_sock;
  2.  
    struct sockaddr_in serv_addr;
  3.  
    char *serv_port = "9190";
  4.  
     
  5.  
    //创建服务器端套接字(监听套接字)
  6.  
    serv_sock = socket(PF_INET,SOCK_STREAM,0);
  7.  
     
  8.  
    //地址信息初始化
  9.  
    memset(&serv_addr,0,sizeof(serv_addr));
  10.  
    serv_addr.sin_family = AF_INET;
  11.  
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  12.  
    serv_addr.sin_port = htons(atoi(serv_port));
  13.  
     
  14.  
    //分配地址信息
  15.  
    bind(serv_sock,(struct sockaddr *)&serv_addr, sizeof(serv_addr));
  16.  
    ....

地址族与数据序列 (转)第18张 

 

免责声明:文章转载自《地址族与数据序列 (转)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇llvm中如何利用分支概率和基本块频率估计css3 动画应用 animations 和transtions transform在加上JavaScript 可以实现硬件加速动画。下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux环境测试机器端口连通性

生产中,有很大一部分的问题都是由于不同机器间网络不同导致的,那么如何判断两台机器之间的连通性?本文介绍几种常见的方式: telnet方法wget方法ssh方法curl方法1. telnet方法格式:telnet ip port说明:ip:是远程主机的ip地址,port:是端口号 示例端口11001不存在,下图所示 端口11000存在,下图所示 2. w...

initializer_list 列表初始化

initializer_list 列表初始化 用花括号初始化器列表初始化一个对象,其中对应构造函数接受一个 std::initializer_list 参数. #include <iostream> #include <vector> #include <initializer_list> template...

8266station初始化和智能配网问题

代码思路是: //station //Esp8266_Station_mode_init(); wifi_set_opmode(STATION_MODE); //Station_mode //定时器任务创建 Esp8266_Timer1_init(1000,1); //1000ms, 1:重复定时 /**...

国威电话机WS824(5D)-3型调试

前端时间搞了一下国威的电话机24个外线,128个内线 一,外线分组调试: 默认设置为所有内线端口可用1,2,13,14,15,16打出。(16个外线组,其中4~12被设置了专线) 设置外线组 ##7871967590 09 *** * 1100,0000 * 0000 1111 # 设置所有分机号白天打入为“全取消” ##787196759011 *** ...

如何分析和提高(C/C++)程序的编译速度?

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。 本文链接:https://www.cnblogs.com/lihuidashen/p/12937085.html 微信链接:https://mp.weixin.qq.com/s/MFOaa-Dw1iNMXuXPfXjLBA 一个别人的vs 2010 的程序...

线程属性--十分重要的概念

http://blog.chinaunix.net/uid-23193900-id-3346199.html 一.线程属性 线程具有属性,用pthread_attr_t表示,在对该结构进行处理之前必须进行初始化,在使用后需要对其去除初始化。我们用pthread_attr_init函数对其初始化,用pthread_attr_destroy对其去除初始化。...