网络编程day1(概念)

 思维导图:

1.子网掩码(重点!)

二级IP地址划分后,主机的基数还是比较大,所以引入了另外一个概念:子网掩码。利用子网掩码可以将主机号进行再次划分:

IP = 网络号 + 子网号 + 主机号

三级划分比较灵活,可以选择划分,也可以选择不划分,可以选择划分出2部分,4部分,8部分...2^n(n=0,1,2......)

1)子网掩码的概念

子网掩码:用于将一个大的IP网络中的主机号划分为若干小的子网络(常用)。

      或者将若干个小网络组合成一个大的局域网(称之为超网技术)。

  1. 指明一个IP地址的哪些位表示的是主机所在的子网
  2. 指明哪些位表示的是主机的位掩码。
  3. 子网掩码不能单独使用,必须结合IP地址一起使用

子网掩码的格式:

  1. 与IP地址一样长的32位无符号整数,是由一串连续的1,后面跟着一串连续的0组成。
  2. 默认子网掩码的格式:
    1. 1的个数与IP地址中网络号的个数一致
    2. 0的个数与IP地址中主机号的个数一致。

2)默认子网掩码

A类IP地址的默认子网掩码:11111111 00000000 00000000 00000000 ===> 255.0.0.0

B类IP地址的默认子网掩码:11111111 11111111 00000000 00000000 ===> 255.255.0.0

C类IP地址的默认子网掩码:11111111 11111111 11111111 00000000 ===> 255.255.255.0

子网掩码是对主机号做再次划分,D类E类没有主机号,所以没有子网掩码。

C类IP地址的默认子网掩码:11111111 11111111 11111111 00000000 ===> 255.255.255.0                                                    11111111 11111111 11111111 10000000 ===> 255.255.255.128

                                              11111111 11111111 11111111 11000000 ===> 255.255.255.192                   

11111111 11111111 11111111 11100000 ===> 255.255.255.224

11111111 11111111 11111111 00000011 ===> 1不连续错误的!!!

 3)格式用法:IP & 子网掩码=子网网段

i. 1个子网网段

192.168.125.229 & 255.255.255.0 

11000000 10101000 01111101 11100101 ===> 192.168.125.229

11111111 11111111 11111111 00000000 ===> 255.255.255.0 

---------------------------------------------------

11000000 10101000 01111101 00000000 ===> 192.168.125.0 子网网段

即192.168.125.229属于192.168.125.0该子网网段。

在00000000-11111111该范围内的主机号,&上255.255.255.0这个子网掩码,得到的结果均为192.168.125.0 子网网段。

即0~255这个范围内的主机号,均为192.168.125.0 子网网段。

所以没有划分出新的子网,所有主机号都在192.168.125.0 子网网段内。

该子网网段可以写作:192.168.125.0/24 (24代表该子网网段是通过有24个1的子网掩码得到)。 这个子网网段内的主机号是多少个 2^8个= 256个。

ii. 2个子网网段

192.168.125.229 & 255.255.255.128

11000000 10101000 01111101 1 1100101 ===> 192.168.125.229

111111111  111111111  111111111 1 0000000 ===> 255.255.255.128

----------------------------------------------------

11000000 10101000 01111101 1 0000000 ===> 192.168.125.128 子网网段

范围:如下范围的主机号[128, 255],& 255.255.255.128得到的结果均192.168.125.128/25  子网网段。

11000000 10101000 01111101 1 0000000 ===> 192.168.125.128

11000000 10101000 01111101 1 11111111===>  192.168.125.255

192.168.125.127 & 255.255.255.128

11000000 10101000 01111101 0 1111111 ===> 192.168.125.127

111111111 111111111 11111111  1 0000000 ===> 255.255.255.128

----------------------------------------------------

11000000 10101000 01111101 0 0000000 ===> 192.168.125.0 子网网段

范围:如下范围的主机号[0, 127],& 255.255.255.128得到的结果均为192.168.125.0/25 子网网段。

11000000 10101000 01111101 0 0000000 ===> 192.168.125.0

11000000 10101000 01111101 0 1111111 ===> 192.168.125.127

综上所述, 通过255.255.255.128可以将192.168.125.0该网络划分出2个子网 每个子网中有2^7个主机号。

子网网段个数 = 2^(子网掩码中多加的1的个数)

每个子网网段中主机号的个数 = 2^(剩余0的个数)

特殊的IP地址:

  1. 每个子网网段中,都有自己的子网网段地址。有效网络号+有效子网号+全是0的主机号 。 掐头
  2. 每个子网网段中,都有自己的子网广播地址。 去尾

总结:每个子网网段都需要掐头去尾

题型

  1. 任务:有如下B类IP地址,130.1.2.3,请问其默认子网掩码是什么?若想要划分出4个子网,请问子网掩码怎么设置,每个子网网段中主机号个数是多少个?每个子网网段中可用主机号个数是多少个?
    1. 默认子网掩码:255.255.0.0
    2. 子网掩码怎么设置: 4 = 2^2,多加2个1, 255.255.192.0
    3. 主机号个数是多少个:子网掩码中剩余14个0,所以每个子网网段中主机号是2^14个
    4. 每个子网网段中可用主机号个数是多少个: 2^14-2个
  1. 130.1.2.3该地址,若使用255.255.192.0子网掩码,请问该网络中所有可用主机号是多少个?
    1. 2^16-2*4(每个子网网段的头和尾)-1(网关)
  1. 192.168.0.0/25,请问该子网掩码是什么,共划分出了几个子网网段。请问该子网网段的网段地址和广播地址分别是什么?
    1. 255.255.255.128
    2. 两个子网网段
    3. 192.168.0.0/25
    4. 192.168.0.127

练习

某个公司有4 部门:行政 研发 售后 营销,每个部门20台电脑接入公司局域网交换机。

如果在192.168.1.0网段划分每个部分的子网,写出所有可用的子网掩码?子网的地址范围是什么

  1. 所以至少划分出4个子网网段:255.255.255. 1100 0000 --》 255.255.255.192 每个子网网段中,主机号的个数为:64个
  2. 划分出8个子网网段:255.255.255. 1110 0000 --》 255.255.255.224 每个子网网段中,主机号的个数为:32个

192.168.1.2~192.168.1.62 192.168.1.0/26

192.168.1.65~192.168.1.126 192.168.1.64/26

192.168.1.129~192.168.1.190 192.168.1.128/26

192.168.1.193~192.168.1.254 192.168.1.192/26

2.网关

网关是一个网络通向其他网络的IP地址

目前家用路由器一般使用192.168.1.1和192.168.0.1作为LAN接口的地址,这个两个也是最常用的网关地址。

【7】域名系统

由于使用IP地址来指定计算机不方便人们记忆,且输入时候容易出错,用字符标识网络种计算机名称方法。

这种命名方法就像每个人的名字,这就是域名(Domian Name)

域名服务器(Domain Name server):用来处理IP地址和域名之间的转换。

域名系统(Domain Name System,DNS):域名翻译成IP地址的软件

一个域名,可以绑定多个ip

域名结构

例如域名 www.baidu.com.cn 从右向左看

cn为高级域名,也叫一级域名,它通常分配给主干节点,取值为国家名,cn代表中国

com为网络名,属于二级域名,它通常表示组织或部门

中国互联网二级域名共40个,edu表示教育部门,com表示商业部门,gov表示政府,军队mil等等

baidu为机构名,在此为三级域名,表示百度

www:万维网world wide web,也叫环球信息网,是一种特殊的信息结构框架。

【8】端口号

为了区分一台主机收到的数据包交给哪个进程处理,使用端口号来区分。程序启动后将端口号和进程绑定在一起。

网络里面的通讯是由 IP地址+端口号 来决定

端口号存储在 2个字节 无符号整数中 (unsigned short int)。[1, 65535]

众所周知的端口号:

1~1023 端口我们编程时候不要使用,是那些”VIP“应用程序占了

TCP 21端口:FTP文件传输服务

TCP 23端口:TELNET终端仿真服务

TCP 25端口:SMTP简单邮件传输服务

TCP 110端口:POP3邮局协议版本3

TCP 80端口:HTTP超文本传输服务

TCP 443端口:HTTPS加密超文本传输服务

UDP 53端口:DNS域名解析服务

UDP 69端口:TFTP文件传输服务

TCP和UDP的端口号是相互独立的

可以使用的:1024~49151,就是我们平时编写服务器使用的端口号

临时端口号:49152~65535,这部分是客户端运行时候动态选择的

2. 跨主机传输

【1】字节序(重点!)

1. 字节序的概念

  1. 字节序是不同类型CPU主机,内存存储 多字节整数 序列的方式。
    1. char 字符串 float double均没有字节序的说法
    2. short int long long long有字节序的说法
  2. 小端字节序:低字节存储在低地址上,高字节存储在高地址上。
  3. 大端字节序:低字节存储在高地址上,高字节存储在低地址上。

ps:首地址都是低地址,数据的读取都是从低地址往高地址读取,经过大小端转换后得出结果。

练习

请简述字节序的概念,并用共用体(联合体)的方式,判断本机的字节序?

2. 本地字节序与网络字节序

本地字节数:主机字节序(Host Byte Order) HBO

网络字节序(Network Byte Order) NBO,网络字节序规定使用大端字节序

在跨主机传输过程中,需要使用统一的字节序,即网络字节序,避免兼容性问题。

3.字节序转换函数

1)htons htonl 主机字节序-->网络字节序

头文件: #include <arpa/inet.h> ​
 uint32_t htonl(uint32_t hostlong);
 uint16_t htons(uint16_t hostshort); 
参数: 指定要转换成网络字节序的整型:分别是32bit和16bit;
 返回值: 成功,返回转换后网络字节序的整型 
#include <stdio.h>
 #include <arpa/inet.h> ​ 
int main(int argc, const char *argv[]) 
{ 
    unsigned int a = 0x87654321; 
    printf("%#x\n", a); //0x87654321 
    printf("%#x\n", htonl(a)); //0x21436587 
​     printf("%#x\n", htons(a)); //0x2143 
    return 0; } ​

2)ntohs ntohl 网络字节序---->主机字节序

头文件: #include <arpa/inet.h> 
原型: uint32_t ntohl(uint32_t netlong); 
       uint16_t ntohs(uint16_t netshort); 
参数: uint32_t hostlong:32位网络字节序整型;
     uint16_t hostshort:16位网络字节序整型; 
    ​ 返回值: 成功,返回转换成主机字节序的整型;

4. 结构体对齐

编译器会对结构体进行对齐,加速CPU取值周期,由于数据对齐也是与操作系统相关,不同的主机如果使用不同的对齐方式,会导致数据无法解析。

所以网络传输结构体的时候需要取消结构体对齐;

#include <stdio.h>
 #pragma pack(1) //设置默认对齐系数 :()中的参数只能填2^n (n=0,1,2,3,4,5......) ​ 
typedef struct { 
    char a; //1
     int b; //4 
    int d; //4
 }_A; ​
 #pragma pack() //重置默认对其系数,重新置为8 
​ typedef struct 
 { 
    char a; //1
     int b; //4
     int d; //4 
}__attribute__((packed)) B; //取消结构体对齐 
​ ​ typedef struct 
{ 
    char a; //1 
          //3     
    int b; //4 
    int d; //4
 }_C;
 ​ int main(int argc, const char *argv[])
 {  
     printf("%ld\n", sizeof(_A)); //9 
     printf("%ld\n", sizeof(_B)); //9
     printf("%ld\n", sizeof(_C)); //12 ​ 
     return 0; }

5. 类型长度

int long int不同操作系统这两个数据类型所占的字节数可能是不一样的

解决方式:可以通过通用类型:uint8_t uint16_t uint32_t

因为涉及到跨平台,不同平台会有不同的字长

#include <stdint.h> ​ 
typedef struct 
{ 
    uint8_t a; //1     
    uint32_t b; //4
    uint16_t d; //2 
}_A;

【2】IP转换

由于IP地址本质上是一个4个字节的无符号整数,所以在跨主机传输中也有字节序的概念。

所以需要将IP地址转换成网络字节序。

"192.168.8.189" ---->本机字节序的整型 0xC0A808BD---->网络字节序0xBD08A8C0

"192.168.31.42"----> 0xC0A81F2A ---->0x2A1FA8C0

1. 点分十进制--->网络字节序

1)inet_aton

头文件:
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>

原型: 
    int inet_aton(const char *cp, struct in_addr *inp);

参数:
     char *cp:源IP地址的点分十进制字符串,
     struct in_addr *inp 存储转换成网络字节序的IP
     typedef uint32_t int_addr_t;
     struct in_addr { 
     in_addr_t s_addr;
 };
返回值:
成功反回非0; 失败,返回0; ​
 只能转换IPv4

例子:
 #define IP "192.168.1.10" //0xC0A8010A

int main(int argc, const char *argv[])

    { 
    struct in_addr inp; if(inet_aton(IP, &inp) == 0)

    { 
        printf("转换失败\n");

          return -1;
     }

    printf("%#X\n", inp.s_addr); //0X0A01A8C0 return 0; }

2)inet_pton

既可以转IPv4也能处理IPv6

头文件: #include <arpa/inet.h>

原型: int inet_pton(int af, const char *src, void *dst);

参数: int af:协议族 
    AF_INET IPV4
     AF_INET6 IPV6
 char *src:指定要转换成网络字节序的点分十进制字符串;
 void* dst 
    typedef uint32_t in_addr_t; 
    struct in_addr 
    { in_addr_t s_addr; }; ​ 
    af == AF_INETa;
     struct in6_addr { }

返回值: 成功,返回1; 失败,返回0或者-1,更新errno;
​
#define IP "192.168.1.3" //0xC0A80103 --> 0x301A8C0 ​ struct in_addr inp;

inet_pton(AF_INET, IP, &inp);

printf("%#X\n", inp.s_addr); //0x301A8C0

3)inet_addr 最常用

头文件:  #include <sys/socket.h>

         #include <netinet/in.h>
         #include <arpa/inet.h>

原型:
         uint32_t inet_addr(const char *cp);

参数: char *cp:源IP地址的点分十进制字符串,例如 “192.168.1.10”;

返回值: 成功,返回转换后的网络字节序IP地址;

          typedef uint32_t in_addr_t; ​ 
          失败,返回INADDR_NONE (usually -1); ​ 只能转换IPv4; ​ ​

例子:

 printf("%#X\n", inet_addr(IP));

2. 网络字节序--->点分十进制

1)inet_ntoa 常用

头文件:
    #include <sys/socket.h>
    
    #include <netinet/in.h> 
    #include <arpa/inet.h>

原型: char *inet_ntoa(struct in_addr in);

参数: struct in_addr in:指定要转换成点分十进制字符串的IP地址;

      typedef uint32_t in_addr_t;
     struct in_addr { 
    in_addr_t s_addr; 
    };

返回值: 成功,返回点分十进制字符串的首地址; ​ 
只能转换IPv4; ​ 
printf("%s\n", inet_ntoa(inp));

2)inet_ntop

头文件:
       #include <arpa/inet.h>
原型:
       const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
参数:
    int af:协议族
            AF_INET         IPV4
            AF_INET6        IPV6
    void* src:存储要转换成点分十进制字符串的IP首地址;
           typedef uint32_t in_addr_t;
           struct in_addr {
               in_addr_t s_addr;
           };
​
            af == AF_INETa;
            struct in6_addr
            {
            }
    char *dst:存储转换后的结果,点分十进制的首地址;
    socklen_t size:缓冲区大小,其实就是指定多大的空间用于转换IP;
返回值:
    成功,返回字符串的首地址,就是dst;
    失败,返回NULL,更新errno;     
​
例子:
     char ip[20];
     if(inet_ntop(AF_INET, &inp, ip, sizeof(ip)) == NULL)
     {
         perror("ient_ntop");
         return -1;                                            
     }
     printf("%s\n", ip);





作业:用共用体的方式判断本机的字节序

#include<myhead.h>
//定义一个共用体
union Byte
{
	unsigned int b;//无符号整数
	char c;
};
	int main(int argc, const char *argv[])
{
	union Byte endianness;
	endianness.b=0x87654321;

	printf("endianness.c=%#x\n",endianness.c);
	if(0x21==endianness.c)
		printf("这是一个小端\n");
	else if(0x87==endianness.c)
		printf("这是一个大端\n");

		return 0;
}

效果图: 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值