1. 程式人生 > 其它 >每日一練(三十一)

每日一練(三十一)

技術標籤:資料結構與演算法linux網路socket

文章目錄

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上時是無法建立連線的。