1. 程式人生 > 實用技巧 >網路程式設計筆記(1)——CS架構和BS架構、TCP/UDP協議、socket概念

網路程式設計筆記(1)——CS架構和BS架構、TCP/UDP協議、socket概念

網路程式設計:

內容目錄

  • CS架構
  • BS架構
  • TCP/UDP協議
  • socket概念

1.C/S架構

C/S即:Client和Server,中文意思:客戶端與伺服器端架構,這種架構也是從使用者層面(也可以是物理層面)來劃分的。

這裡的客戶端一般泛指客戶端應用程式EXE,程式需要先安裝後,才能執行在使用者的電腦上,對使用者的電腦作業系統環境依賴大。

2.B/S架構

B/S即:Browser與Server,瀏覽器端與伺服器端架構,這種架構是從使用者層面來劃分的。

Browser瀏覽器,其實也是一種Client客戶端,只是這個客戶端不需要大家去安裝什麼應用程式,只需在瀏覽器上通過HTTP請求伺服器端相關的資源(網頁資源),客戶端Browser瀏覽器就能進行增刪改查。

3.兩者關係

  • B/S和C/S架構是什麼關係?
    • B/S架構是C/S架構的一種

4.埠

  • 通過埠號找到對應的程式
  • 在計算機上,每一個需要網路通訊的程式,都會開一個埠
  • 在同一個時間只會有一個程式佔用一個埠
  • 埠範圍:0-65535,一般情況下分配8000往後的埠號,避免佔用系統埠

5.TCP/UDP協議

5.1兩個協議的區別

  • TCP協議連線的三次握手,和斷開的四次揮手,特點:
    • 可靠的,面向連線的協議。
    • 傳輸效率低,但是全雙工通訊(傳送快取&接收快取)、面向位元組流。
    • 使用TCP的應用:WEB瀏覽器,電子郵件,檔案傳輸程式。
  • UDP只傳輸,不應答,特點:
    • 提供不可靠,無連線的服務。傳輸效率高(傳送前時延遲小),一對一,一對多,多對一,多對多,面向報文,盡最大努力服務,無擁塞控制
    • 使用UDP的應用:域名系統(DNS),視訊流,IP語音(VoIP).

5.2 網路傳輸流程圖:

6.socket概念

  • 什麼是socket(套接字)

    socket是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,socket其實是一個門面模式:它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,一組簡單的介面就是全部,讓socket去組織資料,以符合指定的協議。
    
    其實站在你的角度上看,socket就是一個模組。我們通過呼叫模組中已經實現的方法建立兩個程序之間的連線和通訊。
    也有人將socket說成ip+port,因為ip是用來標識網際網路中的一臺主機的位置,而port是用來標識這臺機器上的一個應用程式。
    所以我們只要確立了ip和port就能找到一個應用程式,並且使用socket模組來與之通訊。
    
  • 兩種型別的套接字家族

    • 基於檔案型別的套接字(不常用)

      名稱:AF_UNIX
      unix一切皆檔案,基於檔案的套接字呼叫的就是底層的檔案系統來取資料,兩個套接字程序執行在同一機器,可以通過訪問同一個檔案系統間接完成通訊。
      
    • 基於網路型別的套接字(常用,關鍵)

      名稱:AF_INET
      還有AF_INET6被用於ipv6,還有一些其他的地址家族,不過,他們要麼是隻用於某個平臺,要麼就是已經被廢棄,或者是很少被使用,或者是根本沒有實現,所有的地址家族中,AF_INET是應用最廣泛的一個,python支援很多地址家族,但是由於我們只關係網路程式設計,所以大部分時候我們只使用AF_INET
      
  • socket基於TCP和UDP的連線圖

  • 對話應用

    #Server端:
    import socket
    #此為TCP協議的連線
    sk = socket.socket()        #拿到socket的控制代碼
    sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)#避免伺服器重啟的時候報address already in use
    # sk.bind('ip','port')       #使用socket控制代碼繫結ip和埠(ip和埠必須為一個元組)
    sk.bind(('127.0.0.1',8080))
    sk.listen()                 #監聽是否有通訊
    
    conn,addr = sk.accept()     #接收到client:連線:connection,地址:address,獲取一個客戶端的連線,已經完成了三次握手建立起一個連線了。此時為阻塞狀態
    
    ret = conn.recv(1024)       #接收到1024個位元組,如果更改,必須為1024的倍數
    print(ret)
    conn.send(b'server-hi')     #和client傳資訊,必須傳一個byte型別
    ret = conn.recv(1024)
    print(ret.decode('utf-8'))
    conn.send(bytes('黃燜雞米飯',encoding='utf-8'))
    
    conn.close()                #連線斷開
    sk.close()                  #關閉socket
    
    
    #Client端:
    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    
    sk.send(b'Client-hi')
    ret = sk.recv(1024)
    print(ret)
    sk.send(bytes('你吃飯了嗎'.encode('utf-8')))
    ret = sk.recv(1024)
    print(ret.decode('utf-8'))
    
    sk.close()
    
    #一直對話:
    #server端:
    import socket
    sk = socket.socket()        #拿到socket的控制代碼
    sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)      #避免伺服器重啟的時候報address already in use
    #sk.bind('ip','port')       #使用socket控制代碼繫結ip和埠
    sk.bind(('127.0.0.1',8080))
    sk.listen()                 #監聽是否有通訊
    
    conn,addr = sk.accept()     #接收到client:連線:connection,地址:address
    print(addr)
    while True:
        ret = conn.recv(1024).decode('utf-8')       #接收到1024個位元組,如果更改,必須為1024的倍數
        if ret == 'bye':
            break
        print(ret)
        info = input(">>>:")
        conn.send(bytes(info,encoding='utf-8'))     #和client傳資訊,必須傳一個byte型別
    
    conn.close()                #連線斷開
    sk.close()                  #關閉socket
    
    #Client端:
    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    while True:
        info = input('>>>:')
        if info == 'bye':
            sk.send(b'bye')
            break
        sk.send(bytes(info.encode('utf-8')))
        ret = sk.recv(1024).decode('utf-8')
        print(ret)
        if ret == 'bye':
            sk.send(b'bye')
            break
    sk.close()