每日一练(三十一)

1.26 grep 命令

详解:http://c.biancheng.net/linux/grep.html

grep是一个很强大的文本搜索命令,如下:

grep --color -n -A 2 -B 2 -i "gq" /etc/passwd

在/etc/passwd文件下查找含有“gq”的内容,其中--color -n -A 2 -B 2 -i分别表示高亮、显式行号、显示后2行、显示前2行、忽略大小写。

grep还支持的查找方式有:

  • -v:反向排除
  • -n:显示行号
  • -c:统计行数
  • -A x:显示后面x行
  • -B x:显示前面x行
  • -C x:前后各显示x行
  • -i:忽略大小写
  • -l:查找符合条件的文件,并输出列表
  • -L:排除式查找文件
  • -w:准确查找

1.27 assert() 断言函数

是宏,而非函数。assert 宏的原型定义在 <assert.h>(C)、<cassert>(C++)中,其作用是如果它的条件返回错误,则终止程序执行。可以通过定义 NDEBUG 来关闭 assert,但是需要在源代码的开头,include <assert.h> 之前。

assert()主要用于在调试过程中捕捉程序的错误,在大部分编译器下,assert() 是一个宏;在少数的编译器下,assert() 就是一个函数。我们无需关心这些差异,只管把 assert() 当做函数使用即可。

assert() 的用法很简单,我们只要传入一个表达式,它会计算这个表达式的结果:如果表达式的结果为“假”,assert() 会打印出断言失败的信息,并调用 abort() 函数终止程序的执行;如果表达式的结果为“真”,assert() 就什么也不做,程序继续往后执行。

参考:http://c.biancheng.net/ref/assert.html

1.28 字节对齐

什么是字节对齐
计算机中内存大小的基本单位是字节(byte),理论上来讲,可以从任意地址访问某种基本数据类型,但是实际上,计算机并非逐字节大小读写内存,而是以2,4,或8的倍数的字节块来读写内存,如此一来就会对基本数据类型的合法地址作出一些限制,即它的地址必须是2,4或8的倍数。那么就要求各种数据类型按照一定的规则在空间上排列,这就是对齐。这些的目的最重要的考虑是提高内存系统性能。
两种可选的处理方法。
(1)1字节对齐;
(2)自己对结构进行字节填充
具体如下:
使用伪指令#pragma pack(n)(n为字节对齐数)来使得结构间一字节对齐。
attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
attribute ((packed)),取消结构在编译过程中的优化对齐,也可以认为是1字节对齐。

设定结构体、联合以及类成员变量以 n 字节方式对齐

#pragma pack(n) 使用

#pragma pack(push)  // 保存对齐状态
#pragma pack(4)     // 设定为 4 字节对齐

struct test
{
    char m1;
    double m4;
    int m3;
};

#pragma pack(pop)   // 恢复对齐状态

1.29 FTP 主动模式

FTP的两种工作模式主要是针对数据连接来说的,在创建数据连接之前要选择工作模式,模式的选择是由客户端决定的。

控制连接的建立总是客户端向服务器发起的,而数据连接通道的建立分为两种情况:

  • 服务器主动向客户端发起连接:主动模式PORT
  • 服务器被动接受客户端连接:被动模式PASV

主动模式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NsW6sm8e-1612743421295)(https://i.loli.net/2021/02/08/UnyVLbg82xTKPzH.png)]

控制连接是三次握手建立的,通过控制连接客户端可以向服务器发送命令,服务器可以应答。

下面这种主动模式主要用到PORT、LIST命令:

image-20210131193652577 image-20210131194008120

客户端会向服务器发起一个PORT命令,服务器收到之后会应答(200表示准备就绪),接下来客户端发起一个LIST命令,即列出文件信息,这个列表的传输是在数据连接通道中完成的,所以服务器要根据PORT命令中的信息指定服务器要主动连接的端口,服务器通过20端口调用connect主动连接客户端。

所以PORT是在服务器登记客户端的信息,LIST命令之后就要主动建立一个数据连接通道了,一旦数据连接通道建立好之后就可以进行数据的传输。服务器向客户端发送150的应答表示可以进行数据传输,150和226应答之间就是数据的传输了。226指令表示数据传输完成,之后会将数据连接通道关闭。

关于PORT命令的信息:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mSi6kBPk-1612743421299)(https://i.loli.net/2021/02/08/exF2pcoRTEblKJ9.png)]

16的端口号分为高八位p1和低八位p2进行传输。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xAPG90bG-1612743421302)(https://i.loli.net/2021/02/08/83Mf26P4BD15EQz.png)]

image-20210131195305994

客户端发送PORT命令的编程时候,相当于一个服务器模型,即要进行创建socket、绑定临时端口、监听socket、获取临时端口的信息以便于格式化发送。

1.30 FTP 被动模式

被动模式:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-We5Yvmi8-1612743421312)(F:\destop\m笔记\图\image-20210131200038581.png)]

被动模式是服务器接受客户端的连接,在接受PASV命令之后,服务器会告诉告知客户端被动模式的端口以便客户端主动连接服务器。

下面看一下PASV模式下双方交换的命令:
image-20210131200408371

image-20210131200555604

此时服务器上通过accept等待客户端的连接。

image-20210131200835405

PS:当客户端主动关闭socket之后,服务器会通过read返回0来判断socket的关闭

1.31 NAT防火墙对 PORT/PASV的影响

为什么FTP数据连接通道会有主动模式与被动模式之分?是因为NAT或者防火墙对主被动模式有影响。

什么是NAT

image-20210131201347961

NAT就是网络地址的转化,局域网中的主机要想进入互联网,就要有一个公网地址。因为私有的IP地址不可以和公有的IP地址进行通信,所以要通过NAT将局域网的私有IP转换为公网的IP地址。就是建立一个映射关系,由公网IP地址(端口)进行通信。

NAT默认维护由内到外的映射关系,从内向外的连接自然是没问题的。但是从外向内,如果连接的对象IP地址及端口是私有的,那么一般是不会建立成功的,除非用户手动建立映射。主动模式与被动模式的区别也是在这里,由NAT时从内向外没问题,但是从外向内就有问题了。

下面分析一下客户端、服务器分别处于NAT下的主动被动模式。

客户端处于NAT下的主动模式

要知道,主动模式中,客户端首先通过PORT向服务器发送其监听socket及端口号,客户端与服务器进行通信的IP地址及端口都是NAT映射的公网IP地址及端口,当服务器主动连接的时候,服务器是按照PORT中客户端私有IP地址及端口的,所以数据连接通道是无法建立的。

image-20210131203502197

解决办法:

  • 在NAT中手动配置映射关系,这种情况下NAT必须知道服务器主动连接的端口号才可以!!!这就是为什么服务器在主动模式下的端口号是固定的20

所以,当FTP服务器的控制连接可以建立,但是列表刷新不出来,就可能是客户端处于NAT下,且没有手动配置映射关系,导致服务器无法连接到PORT中客户端的端口。

客户端处于NAT下的被动模式

当客户端处于被动模式时,由客户端主动发起连接,这个时候是由NAT内部向外发起连接的,NAT内是维护一个由内向外的表的,所以连接是可以建立成功的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qyhBNT7Z-1612743421317)(https://i.loli.net/2021/02/08/RfyqXHt5Mr4D9gE.png)]

服务器处于NAT下的主动模式

image-20210131203856235

同理,当服务器处于主动模式下,相当于是从NAT内向外建立连接,自然是没有问题。

服务器处于NAT下的被动模式

image-20210131203903735

同理,服务器处于被动模式下时,是客户端向服务器发送建立连接的请求,这个时候客户端知道私有地址以及固定的端口号21,而且服务器也早已经在NAT建立映射了,所以控制通道的建立是ok的。



被动模式下,服务器会告知客户端要连接的端口,但是这个端口并没有在NAT建立映射,所以当客户端的连接请求发送至NAT上时是无法建立连接的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值