python網絡編程基礎與網絡傳輸

網絡編程基礎

  1. C/S B/S 架構python

    C:client端,客戶端
    B:Browser,瀏覽器
    S:server,服務端
    C/S 客戶端與服務器之間的架構:QQ,微信,遊戲,APP等都屬於C/S架構
    優勢:安全性高,個性化設置,功能全面,響應速度快。
    缺點:開發成本高,維護成本高。(基於APP),面向的客戶固定
    B/S:瀏覽器與服務器之間的架構:它屬於C/S架構,最近幾年比較流行的特殊的C/S架構
    優勢:開發維護成本低,面向用戶普遍
    缺點:安全性相對低,響應速度相對慢,個性化的設置單一
  2. 互聯網通訊的原理shell

    1. 首先須要經過各類物理鏈接介質(網線,光纖,無線電波等)將電腦鏈接起來
    2. 其次要準肯定位到對方計算機(定位到軟件)的位置
    3. 經過統一的標準(互聯網協議)進行數據的收發
  3. osi 七層協議(tcp/ip五層協議或tcp/ip四層協議)編程

    七層:應用層,表示層,會話層,傳輸層,網絡層,數據鏈路層,物理層瀏覽器

    五層:應用層(應,表,會),傳輸層,網絡層,數據鏈路層,物理層安全

    四層:應用層(應,表,會),傳輸層,網絡層,網絡接口層(數,物)服務器

    每層運行常見的物理設備:微信

    傳輸層:四層交換機,四層的路由器網絡

    網絡層:路由器,三層交換機架構

    數據鏈路層:網橋,以太網交換機,網卡socket

    物理層:中繼器,集線器,雙絞線

    下面咱們來倒着分析一下五層協議

    1. 物理層

      一系列的物理鏈接介質:網線,光纖,電纜,無線網絡等

      發送的數據是0101011100形式的比特數據流,主要是基於電器特性發送高低電壓(電信號),高電壓對應數字1,低電壓對應數字0

    2. 數據鏈路層:遵循以太網協議

      數據鏈路層的由來:單純的電信號0和1沒有任何意義,必須規定電信號多少位一組,每組表明什麼意思

      數據鏈路層的功能:定義了電信號的分組方式

      以太網協議(ethernet):統一了電信號的分組方式

      Ethernet規定:

      Ethernet規定:一組電信號構成一個數據報,叫作「幀」
      每一數據幀分紅:報頭 head 和數據 data 兩部分
      head 包含:(固定18個字節)
      	發送者/源地址,6個字節
      	接收者/目標地址,6個字節
      	數據類型,6個字節
      data 包含:(最短46個字節,最長1500字節)
      	數據包的具體內容
      head 長度 + data 長度 = 最短64字節,最長1518個字節,超過最大限制就分片發送
      MAC地址:head 中包含的源地址和目標地址的由來,ethernet 規定接入 internet 的設備都必須具有網卡,發送端和接收端的地址即是指網卡地址,即MAC地址
      MAC地址:每塊網卡出廠時都被燒製上一個世界惟一的MAC地址,長度爲48位2進制,一般由12位16進制數表示(前六位是廠商編號,後六位是流水線號)
      
      廣播: 計算機最原始的通訊方式就是吼.
      數據的分組(源地址目標地址) + 廣播: 理論上個人計算機就能夠通訊了.可是效率過低,每臺計算機都須要接收廣播的消息,查看是不是給本身的數據.比廣播風暴還要嚴重.
      因此: 廣播它是有範圍的,在同一子網,局域網內是經過廣播的方式,發消息.
    3. 網絡層:遵循IP協議

      網絡層由來:是爲了肯定目標計算機在局域網內的位置

      網絡層功能:引入一套新的地址用來區分不一樣的廣播域/子網,這套地址即網絡地址

      IP協議:規定網絡地址的協議叫 IP 協議,它定義的地址稱之爲 ip 地址,普遍採用的v4版本即ipv4,它規定網絡地址由32位2進製表示

      一個ip地址一般寫爲四段十進制數,如:172.16.10.1

      ip地址範圍:0.0.0.0 - 255.255.255.255

      ip地址分紅兩個部分:

      網絡部分:標識子網

      主機部分:標識主機

      注意:單純的ip地址段只是標識了ip地址的種類,從網絡部分或主機部分都沒法辨識一個ip所處的子網

      例:172.16.10.1與172.16.10.2並不能肯定兩者處於同一子網

      子網掩碼:

      所謂」子網掩碼」,就是表示子網絡特徵的一個參數。它在形式上等同於IP地址,也是一個32位二進制數字,它的網絡部分所有爲1,主機部分所有爲0。好比,IP地址172.16.10.1,若是已知網絡部分是前24位,主機部分是後8位,那麼子網絡掩碼就是11111111.11111111.11111111.00000000,寫成十進制就是255.255.255.0。
      知道」子網掩碼」,咱們就能判斷,任意兩個IP地址是否處在同一個子網絡。方法是將兩個IP地址與子網掩碼分別進行AND運算(兩個數位都爲1,運算結果爲1,不然爲0),而後比較結果是否相同,若是是的話,就代表它們在同一個子網絡中,不然就不是。
      好比,已知IP地址172.16.10.1和172.16.10.2的子網掩碼都是255.255.255.0,請問它們是否在同一個子網絡?二者與子網掩碼分別進行AND運算,
      172.16.10.1:10101100.00010000.00001010.000000001
      255255.255.255.0:11111111.11111111.11111111.00000000
      AND運算得網絡地址結果:10101100.00010000.00001010.000000001->172.16.10.0
      172.16.10.2:10101100.00010000.00001010.000000010
      255255.255.255.0:11111111.11111111.11111111.00000000
      AND運算得網絡地址結果:10101100.00010000.00001010.000000001->172.16.10.0
      結果都是172.16.10.0,所以它們在同一個子網絡。
      總結一下,IP協議的做用主要有兩個,一個是爲每一臺計算機分配IP地址,另外一個是肯定哪些地址在同一個子網絡。

      ip數據包

      ip數據包也分爲head和data部分,無須爲ip包定義單獨的欄位,直接放入以太網包的data部分

      head:長度爲20到60字節

      data:最長爲65,515字節。

      而以太網數據包的」數據」部分,最長只有1500字節。所以,若是IP數據包超過了1500字節,它就須要分割成幾個以太網數據包,分開發送了。

    4. 傳輸層:遵循端口協議(tcp/udp協議)

      傳輸層的由來:網絡層的IP地址幫咱們區分子網,以太網的MAC幫咱們找到主機, 而後你們使用的都是應用程序,你的電腦上可能同時開啓QQ,微信等多個應用程序那麼咱們經過ip和Mac找到了目標計算機,如何標識這臺主機上的應用程序,答案就是端口,端口即應用程序與網卡關聯的編號

      傳輸層功能:創建端口到端口的通訊

      端口: 0~65535端口號.

      ​ 1~1023系統佔用的端口號.

      ​ 1024~8000以內:通常都是有軟件佔用.

      ​ 自定義端口: 8000 之後

      tcp協議:

      可靠傳輸,TCP數據包沒有長度限制,理論上能夠無限長,可是爲了保證網絡的效率,一般TCP數據包的長度不會超過IP數據包的長度,以確保單個TCP數據包沒必要再分割。

      以太網頭|ip頭|tcp頭|數據

      udp協議:

      不可靠傳輸,」報頭」部分一共只有8個字節,總長度不超過65,535字節,正好放進一個IP數據包。

      以太網頭|ip頭|udp頭|數據

      TCP的三次握手四次揮手

      三次握手:

      第一次: 客戶端向服務器發送創建聯繫的syn請求和seq序號

      第二次: 服務器向客戶端回覆ack確認號和創建聯繫的syn請求和seq序號

      第三次: 客戶端向服務器回覆ack確認號

      四次揮手:

      第一次: 客戶端向服務器發送斷開聯繫的fin請求和seq序號

      第二次: 服務器向客戶端回覆ack確認號

      第三次: 服務器向客戶端發送斷開聯繫的fin請求和seq序號

      第四次: 客戶端向服務器回覆ack確認號

      udp與tcp的區別

      一、TCP的優缺點
      (1)TCP的優勢:
      TCP的優勢是:可靠、穩定。它體如今TCP在傳遞數據以前,會有三次握手來創建鏈接;在數據傳遞時,採用校驗和、序列號、確認應答、超時重發、流量控制、擁塞控制,爲了提升性能,還採用了滑動窗口、延遲應答和捎帶應答等機制;在數據傳完後,會斷開鏈接以節約系統資源。
      
      (2)TCP的缺點:
      TCP的缺點:運行速度慢,效率低,佔用系統資源多,易被攻擊。由於TCP在傳遞數據以前,要先創建鏈接,這會消耗時間;在數據傳遞時,確認機制、重傳機制、擁塞控制機制等都會消耗大量的時間,並且要在每臺設備上維護全部的傳輸鏈接,每一個鏈接都會佔用系統的CPU、內存等資源;TCP有確認機制、三次握手機制,這致使TCP容易受到DOS、DDOS、CC等攻擊。收到STN洪水攻擊,是由於使用 TCP的時候服務器端須要listen,這時須要設置backlog。
      
      二、UDP的優缺點
      (1)UDP的優勢:運行速度較快,比TCP安全。
      1)運行速度快,由於 UDP鏈接沒有TCP的三次握手、確認應答、超時重發、流量控制、擁塞控制等機制,並且UDP是一個無狀態的傳輸協議,因此它在傳遞數據時很是快。
      2)較安全,由於沒有TCP的那些機制,UDP較TCP被攻擊者利用的漏洞就會少一些。但UDP也是沒法避免攻擊的,好比:UDP Flood攻擊等。
      (2)UDP的缺點:不可靠,不穩定。
      由於UDP沒有TCP那些可靠的機制,在數據傳遞時,若是網絡質量很差,就會很容易丟包。
      
      三、TCP和UDP的特色
      (1)TCP的特色
      TCP協議是一種有鏈接、可靠的、面向字節流、相對比較慢、點對點的傳輸層協議。TCP協議適用於對可靠性要求比較高的場合。
      (2)UDP的特色
      UDP協議是一種無鏈接,不可靠、面向數據報、速度比較快、可實現一對一,多對一的傳輸層協議。UDP協議適用於對實時性有要求的場合。由於UDP不保證可靠性,因此UDP也沒有重傳機制,也沒有擁塞機制,它只是盡最大努力交付數據。

      使用TCP的應用:Web瀏覽器;文件傳輸程序。

      使用UDP的應用:域名系統 (DNS);視頻流;IP語音(VoIP),微信qq。

    5. 應用層:遵循應用軟件本身定義的協議

      應用層由來: 用戶使用的都是應用程序,均工做於應用層,互聯網是開放的,你們均可以開發本身的應用程序,數據多種多樣,必須規定好數據的組織形式

      應用層功能:規定應用程序的數據格式。

2. 網絡傳輸

  1. socket套接字.

    五層協議: 從傳輸層包括傳輸層如下,都是操做系統幫助咱們封裝的各類head.你不用去關心.應用層與傳輸層之間存在一個socket套接字

    # socket的套接字
    '''
    socket 套接字,它存在於傳輸層與應用層之間的抽象層,
        1. 避免你學習各層的接口,以及協議的使用, socket已經封裝好了全部的接口.
            直接使用這些接口或者方法便可,使用起來方便,提高開發效率.
        2. socket就是一個模塊.經過使用學習模塊提供的功能,
            創建客戶端與服務端的通訊,使用方便.
    '''
  2. 單個客戶與服務端通訊.

    服務端:

    import socket
    # phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 1. 建立socket對象
    phone = socket.socket() # 能夠不寫,默認TCP協議下的連接模式
    # 2. 綁定ip地址和端口
    phone.bind(('127.0.0.1', 8848))  # '127.0.0.1'本地迴環地址
    # 3. 監聽
    phone.listen(5)
    # 4. 接收鏈接
    conn, addr = phone.accept()  # 程序夯住,等待客戶端的數據
    from_client_data = conn.recv(1024)  # 至多接收1024個字節
    print(f'來自客戶端{addr}消息{from_client_data.decode("utf-8")}')
    to_client = input('>>>')
    conn.send(to_client.encode('utf-8'))
    
    conn.close()
    phone.close()

    客戶端:

    import socket
    # 1. 建立socket對象
    phone = socket.socket() # 能夠默認不寫
    # 鏈接服務器ip地址與端口
    phone.connect(('127.0.0.1', 8848))
    # 發消息
    to_server = input('>>>').strip()
    phone.send(to_server.encode('utf-8'))
    # 接收消息
    from_server_data = phone.recv(1024)  # 夯住,等待服務端的數據傳過來
    print(f'來自服務端消息:{from_server_data.decode("utf-8")}')
    # 關機
    phone.close()
  3. 通訊循環.

    服務端:

    import socket
    phone = socket.socket() # 能夠默認不寫
    phone.bind(('127.0.0.1', 8848))  # 本地迴環地址
    phone.listen(5)
    conn, addr = phone.accept()  # 程序夯住
    while 1:
        from_client_data = conn.recv(1024)  # 至多接收1024個字節
        print(f'來自客戶端{addr}消息{from_client_data.decode("utf-8")}')
        to_client = input('>>>')
        conn.send(to_client.encode('utf-8'))
    conn.close()
    phone.close()
    # 不管你的客戶端是否正常關閉,服務端都應該正常關閉,而不是報錯.
    # 改進版
    import socket
    phone = socket.socket() # 能夠默認不寫
    phone.bind(('127.0.0.1', 8888))  # 本地迴環地址
    phone.listen(5)
    conn, addr = phone.accept()  # 程序夯住
    while 1:
        try:
            from_client_data = conn.recv(1024)  # 至多接收1024個字節
            if from_client_data == b'q': # 接受到客戶端發來的q 退出循環
                break
            print(f'來自客戶端{addr}消息{from_client_data.decode("utf-8")}')
            to_client = input('>>>')
            conn.send(to_client.encode('utf-8'))
        except ConnectionResetError:
            break
    conn.close()
    phone.close()

    客戶端:

    import socket
    phone = socket.socket() # 能夠默認不寫
    phone.connect(('127.0.0.1', 8888))
    while 1:
        to_server = input('>>>').strip()
        if to_server.upper() == 'Q':  # 若是用戶輸入的是Q/q
            phone.send('q'.encode('utf-8'))  # 向服務端發送 q
            break  # 退出循環
        phone.send(to_server.encode('utf-8'))
        from_server_data = phone.recv(1024)  # 夯住,等待服務端的數據傳過來
        print(f'來自服務端消息:{from_server_data.decode("utf-8")}')
    phone.close()
  4. 通訊,鏈接循環.

    服務端:

    import socket
    phone = socket.socket()
    phone.bind(('127.0.0.1', 8888))
    phone.listen(5)
    while 1:
        conn, addr = phone.accept()  # 程序夯住
        while 1:
            try:
                from_client_data = conn.recv(1024)  # 至多接收1024個字節
                if from_client_data == b'q':
                    break
                print(f'來自客戶端{addr}消息{from_client_data.decode("utf-8")}')
                to_client = input('>>>')
                conn.send(to_client.encode('utf-8'))
            except ConnectionResetError:
                break
        conn.close()
    phone.close()

    客戶端:

    import socket
    phone = socket.socket() # 能夠默認不寫
    phone.connect(('127.0.0.1', 8888))
    while 1:
        to_server = input('>>>').strip()
        if to_server.upper() == 'Q':
            phone.send('q'.encode('utf-8'))
            break
        phone.send(to_server.encode('utf-8'))
        from_server_data = phone.recv(1024)  # 夯住,等待服務端的數據傳過來
        print(f'來自服務端消息:{from_server_data.decode("utf-8")}')
    phone.close()
  5. 利用socket完成獲取遠端命令的示例.

    服務端

    import socket
    import subprocess
    phone = socket.socket()
    phone.bind(('127.0.0.1', 8888))
    phone.listen(5)
    conn, addr = phone.accept()
    while 1:
        try:
            cmd = conn.recv(1024) #  dir
            obj = subprocess.Popen(cmd.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,)
            result = obj.stdout.read() + obj.stderr.read()
            conn.send(result)
        except ConnectionResetError:
            break
    conn.close()
    phone.close()

    客戶端

    import socket
    phone = socket.socket()
    phone.connect(('127.0.0.1', 8888))
    while 1:
        cmd = input('>>>').strip()
        phone.send(cmd.encode('utf-8'))
        result = phone.recv(1024)  # 夯住,等待服務端的數據傳過來
        print(result.decode('gbk'))
    phone.close()
相關文章
相關標籤/搜索