day17-網路程式設計(上)

死不悔改奇男子發表於2024-04-21

1.必備基礎

你必須瞭解的網路相關裝置和基礎概念。

1.1 網路架構

假設 alex 上了一個野雞大學買了一臺電腦,電腦裡存了1部小電影,整宿整宿的在宿舍反覆的看。

image

alex 如何想要和室友 於超 進行收發資料,可以透過一根網線來進行連線,並進行資料的傳輸。

image

1.1.1 交換機

其他2位室友如何也想和他們的電腦相互連線然後進行資源的共享,此時就需要一個裝置 【二層交換機】元件一個區域網。

當電腦接入交換機之後,我們需要為每臺電腦分配一個IP,例如:
    - 電腦1:192.168.10.1
    - 電腦2:192.168.10.2
    - 電腦3:192.168.10.3
    - 電腦4:192.168.10.4
區域網內容個電腦之間是基於ARP協議來進行通訊,例如:A電腦向 IP為192.168.10.3的另一個電腦傳送訊息。

第一步:A封裝資料包,此時只知道目標IP不知道目標mac地址(未知mac地址時預設會設定為FF)。
第二步:將資料包傳送到交換機,交換機透過廣播的形式將資料傳送給所有電腦。
第三步:目標電腦接收到資料包後,監測自己是否是目標IP。
		- 是,收到資料並回復。
		- 不是,則丟棄包。

為防止每次傳送訊息都是廣播形式,每臺電腦的內部都為維護了一個ARP表,接受到資料時(無論是否自己的)都會記錄自己瞭解的IP和MAC的對應關係,例如:
    Internet地址			       實體地址
    192.168.10.1            14-9d-da-2a-dd-0a
    192.168.10.3            14-9d-da-2a-dd-0c
    ...
    
以便於下次在傳送訊息時,就知道了目標的mac地址,直接讓交換機轉發給指定的電腦(單播)。

同時,當有訊息傳送經過二層交換機時他的內容也會維護記錄了交換機介面和連線的電腦的mac地址的對應關係,例如:
    介面(網路卡)               mac地址
      介面1              14-9d-da-2a-dd-0A
      介面2              14-9d-da-2a-dd-0B
      介面3              14-9d-da-2a-dd-0C
      ...
這樣一來,交換機在進行資料轉發時,效率就更高了。

注意:每臺電腦出廠時在網路卡中都設定了唯一的mac地址(不重複),網路卡整合在主機板上,如果更換了主機板則mac地址也會變更。

image

image

頭部資訊:xxx
資料:你好
頭部資訊:xxx
資料:收到

1.1.2 路由器

多個宿舍之間想想要組建一個相互可以通訊網路,此時需要【二層交換機】和【企業路由器】配合組建稍微大一點的區域網(同時也可緩解廣播風暴)。

劃分好網路結構之後,其實會給各宿舍的電腦分配IP和閘道器,例如:
   宿舍A:
		- 電腦1:192.168.10.1  閘道器:192.168.10.254
		- 電腦2:192.168.10.2  閘道器:192.168.10.254
		- 電腦3:192.168.10.3  閘道器:192.168.10.254
		- 電腦4:192.168.10.4  閘道器:192.168.10.254
   宿舍B
		- 電腦1:192.168.20.1  閘道器:192.168.20.254
		- 電腦2:192.168.20.2  閘道器:192.168.20.254
		- 電腦3:192.168.20.3  閘道器:192.168.20.254
		- 電腦4:192.168.20.4  閘道器:192.168.20.254

然後再在路由器中配置路由表(包含網段和路由器上的介面的對應關係),例如:
	 介面             IP
     eth0   	  192.168.10.254(192.168.10網段)
     eth1   	  192.168.20.254(192.168.20網段)
    
想與外部網路通訊,需要配置閘道器,閘道器就是路由表中配置的指向此網段的IP。其實就類似於貿易出口都需要經過海關。
資料通訊的過程結合了APR協議和IP協議,例如:宿舍A的電腦1向宿舍B的電腦3傳送訊息(目標IP:192.168.20.3)。

簡化過程:
	- 宿舍A的電腦1,透過廣播或單播將資料傳送到網管(路由器)
    - 路由器接收到資料之後,再透過對應的介面把資料透過廣播的形式傳送到宿舍B。
注意:各自區域網內透過學習並記錄相關mac地址後,就可以不再使用廣播形式,而是使用單播來傳送訊息了。

image

image

1.1.3 三層交換機

三層交換機整合了 交換機 & 路由器的功能(大部分路由器功能),上述的三個裝置其實可以用一個三層交換機就可以搞定。

按照下圖,在三層交換機上分別做如下幾件事:

1. 劃分兩個vlan,模擬出來路由器的兩個介面。
2. 將交換機的介面劃分給指定的vlan,例如:
	介面1、2、3劃分給一個vlan,相當於交換機連線上了路由器。
    介面4、5、6劃分給一個vlan,相當於交換機連線上了路由器。
3. 電腦連線上交換機。
4. 進行相應的配置。
	宿舍A(左邊)電腦配置:
    	- 電腦1:192.168.10.1  閘道器:192.168.10.254	對應交換機介面:1
		- 電腦2:192.168.10.2  閘道器:192.168.10.254	對應交換機介面:2
		- 電腦3:192.168.10.3  閘道器:192.168.10.254	對應交換機介面:3
	宿舍B(右邊)電腦配置:
		- 電腦1:192.168.20.1  閘道器:192.168.20.254	對應交換機介面:4
		- 電腦2:192.168.20.2  閘道器:192.168.20.254	對應交換機介面:5
		- 電腦3:192.168.20.3  閘道器:192.168.20.254	對應交換機介面:6
	
    交換機中的路由配置:
    	  介面               IP
         左vlan   	  192.168.10.254(192.168.10網段)
         右vlan   	  192.168.20.254(192.168.20網段)
        
透過上述的配置之後,就可以實現宿舍A和宿舍B的網路通訊了。

image

1.1.4 小型企業基礎網路架構

image

1.1.5 家庭網路架構

家用路由器整合了是交換機和路由的功能(效能差、價格便宜)。

image

1.1.6 網際網路

image

1.2 網路核心詞彙

1.2.1 子網掩碼和IP

之前說過,接入網路裝置後,需要一個IP來代指次電腦,例如:192.168.10.1 。

IP其是一個32位的二進位制,為了便於記憶就將它分為4組,每組8位,由小數點分開,例如:

二進位制表示:00000000.10010111.11111111.00001111
十進位制表示:251.151.255.15

0~255
192.178.11.211
192.178.11.311

在網路中的每臺電腦都會有一個IP與之繫結,這樣透過IP就可以找到相應的電腦。

一個IP地址可以劃分為兩個部分,即:網路地址 + 主機地址。

  • 問題1:如何確定網路地址和主機地址呢?

    透過子網掩碼就可以確定IP的網路地址和主機地址。
    
    示例1:
        	IP:192.168.1.199      11000000.10101000.00000001.11000111
    	子網掩碼:255.255.255.0     11111111.11111111.11111111.00000000
    此時,網路地址就是前24位 + 主機地址是後8位。你可能見過有些IP這樣寫 192.168.1.199/24,意思也是前24位是網路地址。
    
    
    示例2:
        	IP:192.168.99.254     11000000.10101000.01100011.11111110
    	子網掩碼:255.255.240.0     11111111.11111111.11111100.00000000
    此時,網路地址就是前22位 + 主機地址是後10位。你可能見過有些IP這樣寫 192.168.99.254/22,意思也是前22位是網路地址。
    
  • 問題2:劃分 網路地址 + 主機地址 的意義是什麼?

    網路地址相同的IP,也稱為屬於同一個網段。
    在區域網內只有同一個網段的IP才能相互通訊,不同網段IP想要通訊需要藉助路由的轉發才能通訊。
    
    當了解子網掩碼之後,其實就可以確定某個網段可以容納的主機個數,例如:
    【IP: 192.168.10.2  掩碼:255.255.255.0】 和 【192.168.10.251 掩碼:255.255.255.0】 資料同一個網段。
    
    	示例網段的主機範圍:11000000.10101000.00001010. 00000001  ~  11000000.10101000.00001010.  11111110
    	                 --------------------------              --------------------------
    	                          網路地址                                   網路地址
    				           192.168.10.1                 ~           192.168.10.254
                               
    【IP: 192.168.8.1  掩碼:255.255.240.0】 和 【192.168.11.254 掩碼:255.255.240.0】 資料同一個網段。
    	子網掩碼:255.255.240.0
    	示例網段的主機範圍:11000000.10101000.000010 00.00000001  ~  11000000.10101000.000010 11.11111110
    	                 11111111.11111111.111111 00.00000000
    	                 ------------------------                 ------------------------
    	                          網路地址                                   網路地址
    				           192.168.8.1                 ~           192.168.11.254
    				           
    【IP: 192.168.96.1  掩碼:255.255.240.0】 和 【192.168.99.254  掩碼:255.255.240.0】 資料同一個網段。
    	示例網段的主機範圍:11000000.10101000.011000 00.00000001  ~  11000000.10101000.011000 11.11111110
    	         
    	                 ------------------------                 ------------------------
    	                          網路地址                                   網路地址
    				           192.168.96.1                 ~           192.168.99.254    
    

    image
    image

1.2.2 DHCP

在一個區域網內想要給某臺電腦分配IP有兩種方式:

  • 手動設定,開啟指定選單欄在裡面輸入相應的IP資訊。

  • 自動獲取

    - 在電腦端,IP地址獲取方式設定為自動。
    - 在路由器或三層交換機,開啟DHCP服務,並設定IP地址池。(家用路由器上也是基於DHCP服務自動分配的IP)
    
    這樣,電腦只要連線只該網路,DHCP服務就會為它自動分配IP、子網掩碼、閘道器。
    

image
image

1.2.3 內網和公網IP

一般情況下,內網IP都用這些(潛規則):
	- 10.0.0.0 到 10.255.255.255
	- 172.16.0.0 到172.31.255.255
	- 192.168.0.0 到192.168.255.255

之前我們自己在一個區域網內為電腦分配的IP都稱為內網IP,基於內網IP可以在一個區域網內進行相互通訊(也需要相關的配置)。

image

如果想要透過網際網路進行通訊,就必須藉助公網IP。例如,右邊家庭電腦想訪問左邊某公司伺服器上的部署的網站:

  • 第一步:左邊公司,去運營商申請公網的固定IP(辦理專線寬頻時運營商會分配至少1個固定的IP地址),其實運營商就是將你拉的這個專線和固定IP建立繫結關係。(假設公網IP:123.206.15.88)
  • 第二步:配置公網IP與指定伺服器的轉發規則。
  • 第二步:右邊家庭,如果想要訪問某個公司伺服器上的網網站,只需要執行指定IP:123.206.15.88,運營商就會根據IP找到與之關聯的公司專線,並透過公司路由器、防火牆等裝置找到指定的伺服器。

按理說,每個從運營商接入網的使用者都可以有一個外網IP,但由於全球使用者太多而IP根本就不夠分配,所以,運營商網路會進行劃分,讓多個家庭寬頻使用者共用一個公網IP(動態,可能每次上網公網IP都不一樣)。

讓家庭使用者想要透過網路訪問訪問其他IP時,先發給運營商由運營商向外轉發到其他IP。

注意:外部使用者想要訪問家庭寬頻的IP時,運營商不會把請求轉發到我們的電腦。

image

所以,以後如果你想開發一個網站供全球的使用者訪問,那你就需要做以下幾件事:

  • 拉專線,申請固定公網IP
  • 買一臺伺服器(就是效能好的電腦)
  • 公網IP繫結至此伺服器
  • 將寫好的程式碼放在伺服器上並執行起來

這樣就可以搞定了...

擴充套件:IPv4和IPv6

IPv4,長度為 32 位(4 個位元組), 格式:A.B.C.D
IPv6,長度為 128 位(16 個位元組),用":"分成8段,格式:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX(每個X是一個16進位制數)。

1.2.4 雲伺服器

大家可能之前聽說過:阿里雲、騰訊雲、亞馬遜aws等之類的平臺都在搞雲伺服器,那是個啥?

image

簡單的說:他們造了一個機房(網咖),買了很多很多的伺服器(高效能電腦),然後將他們放在機房,然後通電+通網,主要對外去租賃這些伺服器資源,讓使用者不必再自己 拉專線+配置網路+買伺服器。

假設,你想要在騰訊雲租一臺伺服器,就可以根據自己的需求去選擇配置,騰訊雲會根據配置在他的物理機上虛擬出一個伺服器,並進行相應的環境初始化並繫結公網固定IP,這樣你就可以快速擁有一臺可以被大家訪問的伺服器了。

注意:一臺效能非常高的物理機虛擬出很多虛擬機器,類似於你在自己電腦上透過vmware、parallel等搞出多個虛擬機器。
image

1.2.5 埠

image

假設,你在騰訊租了一臺雲伺服器(外網IP:123.206.15.88),然後又開發了 2 個網站執行在伺服器上。

那麼問題來了,使用者在自己的電腦或手機上如何來分別訪問同一臺伺服器上兩個程式呢?

其實,在計算機中有一個 的概念,每個程式想要透過網路進行通訊都必須要指定一個埠,例如:

  • 網站A:使用8001埠,那麼使用者在自己電腦上或手機上訪問時指定 IP和埠 即可,如: 123.206.15.88:8001
  • 網站B:使用8002埠,那麼使用者在自己電腦上或手機上訪問時指定 IP和埠 即可,如: 123.206.15.88:8002

注意:埠的取值範圍:0 ~ 65535,很多埠在計算機的內部已被使用,我們平時自定義時儘量選擇5000之後的埠。

示例:訪問百度
image

提示:如果在瀏覽器上只寫IP不寫埠,則預設是80埠。

1.2.6 域名

假設你創業開發了一個網站,使用者很難記住你的公網IP:123.206.15.88:80 123.206.15.88

所以,域名就誕生了,讓域名和IP建立對應關係,使用者只需要記住域名就可以了,例如:

www.baidu.com   -->  110.242.68.3
www.taobao.com  --> 121.18.239.232
...

注意:域名只是和IP建立了對應關係,與埠無關 www.baidu.com:80
image

在使用者在自己的電腦或手機上輸入域名去訪問時,其實要執行兩個步驟:

  • 根據域名尋找IP。(尋找IP)
  • 獲得IP之後,再透過IP再去訪問指定伺服器。

在電腦上屬如域名後,尋找IP的過程如下:

  • 第一步:在自己電腦的DNS快取記錄中尋找 域名對應的IP,如果未命中,則執行下一步。

  • 第二步:在自己電腦的hosts檔案中尋找,如果未命中,則執行下一步。

    - mac系統:/etc/hosts 檔案中
    - win系統:C:\Windows\System32\drivers\etc\hosts 檔案中
    
    # 內容示例
    127.0.0.1	localhost
    255.255.255.255	broadcasthost
    127.0.0.1 kubernetes.docker.internal
    192.168.1.55 www.pythonav.com
    
  • 第三步:在自己電腦上找到DNS配置的地址(本地域名伺服器),去這個地址尋找域名對應的IP,如果未命中,則執行下一步。
    image

    常見的DNS伺服器地址:
    	114.114.114.114(114 DNS)
        223.5.5.5(阿里 AliDNS)
        8.8.8.8(Google DNS,隨著Google在中國的沒落和國內官方的限制,已經不是太好用了)
        ...
        各大運營商也有相應的DNS伺服器...
        
    如果你選擇的是自動獲得DNS,那麼就會使用本地運營商的DNS伺服器了。
    
  • 第四步:去根域名伺服器中詢問(全球共13臺根域名伺服器,距離中國最近的一臺是在日本)

    image

問題來了

瞭解域名是怎麼回事之後?現在你如果想要讓自己的網站透過域名來訪問,應該怎麼辦呢?【目前瞭解即可】

  • 租一個域名

    ICANN,域名的總管理者(美國一個非營利機構),它僅制定域名政策,註冊業務它會授權給一些頂級註冊商。
    頂級註冊商,可以對外銷售域名,但要受國家 網際網路絡資訊中心的管理。例如:中國萬網(阿里雲收購),中國新網,新網互聯,商務中國,中國頻道等。
    代理註冊商,頂級註冊上可以再招一些代理幫助他們賣域名。
    

    image

  • 備案

    現在國內註冊域名後,需要進行備案(提交一些網站、個人或企業 等資訊)後才能使用。
    註冊成功後,可按照引導備案:https://beian.aliyun.com/
    
    注意:國外的域名無需備案就能使用。
    
  • 域名解析

    讓域名和IP建立關聯關係,並將關係同步到相關:本地域名伺服器 和 根域名伺服器(含頂級和二級域名伺服器)。
    

    image

    image

2. 網路程式設計

image

Python中內建了一個socket模組,可以快速實現網路之間進行傳輸資料。例如:

  • 服務端,放在左邊雲伺服器中(有固定IP)

    import socket
    
    # 1.監聽本機的IP和埠
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('123.206.15.88', 8001)) # IP,埠
    sock.listen(5) # 支援排隊等待5人
    
    while True:
        # 2.等待,有人來連線(阻塞)
        conn, addr = sock.accept() # 等待客戶端來連線(阻塞)
    
        # 3.等待,連線者傳送訊息(阻塞)
        client_data = conn.recv(1024) # 等待接收客戶端發來資料
        print(client_data.decode('utf-8')) # 位元組
    
        # 4.給連線者回復訊息
        conn.sendall("hello world".encode('utf-8'))
    
        # 5.關閉連線
        conn.close()
    
    # 6.停止服務端程式
    sock.close()
    
  • 客戶端,放在右邊使用者電腦上

    import socket
    
    # 1. 向指定IP傳送連線請求
    client = socket.socket()
    client.connect(('123.206.15.88', 8001)) # 向服務端發起連線(阻塞)10s
    
    # 2. 連線成功之後,傳送訊息
    client.sendall('hello'.encode('utf-8'))
    
    # 3. 等待,訊息的回覆(阻塞)
    reply = client.recv(1024)
    print(reply)
    
    # 4. 關閉連線
    client.close()
    

上述示例需要藉助於網際網路,你至少需要租一臺雲伺服器才能通訊。

為了節省學習成本,大家可以在自己電腦上模擬【服務端】和【客戶端】,等以後專案開發完畢後,再租伺服器並部署到伺服器上。

注意:在自己本地執行上述程式碼時,要監聽和連線時的IP地址。

image

image

image

當然,你也可以把在自己的區域網內找兩臺電腦,A作為服務端,B作為客戶端,這樣兩者也可以通訊。

服務端的程式碼需修改:監聽的IP修改為A的IP地址。
客戶端的程式碼需修改:連線的IP修改為A的IP地址(客戶端要去找到服務端,並與服務端建立連線)。

注意事項:

  • 本機:

    服務端IP:127.0.0.1  / 192.168.28.92(區域網IP)
    
  • 區域網:

    服務端IP:192.168.28.92(區域網IP)
    
  • 網際網路

    服務端IP:123.206.15.88(外網IP)
    

案例:智障客服

  • 服務端

    import socket
    
    # 1.監聽本機的IP和埠
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', 8001))  # 127.0.0.1 或 檢視自己區域網本地IP地址
    sock.listen(5)
    
    while True:
        # 2.等待,有人來連線(阻塞)
        conn, addr = sock.accept()
        print("有人來連線了...")
    
        # 3.連線成功後立即傳送
        conn.sendall("歡迎使用xx系統,請輸入您想要辦理的業務!".encode("utf-8"))
    
        while True:
            # 3.等待接受資訊
            data = conn.recv(1024)
            if not data:
                break
            data_string = data.decode("utf-8")
    
            # 4.回覆訊息
            conn.sendall("你說啥?".encode("utf-8"))
        print("斷開連線了")
        # 5.關閉與此人的連線
        conn.close()
    
    # 6.停止服務端程式
    sock.close()
    
    
  • 客戶端

    import socket
    
    # 1. 向指定IP傳送連線請求
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('127.0.0.1', 8001))
    
    # 2.連線成功後,獲取系統登入資訊
    message = client.recv(1024)
    print(message.decode("utf-8"))
    
    while True:
        content = input("請輸入(q/Q退出):")
        if content.upper() == 'Q':
            break
        client.sendall(content.encode("utf-8"))
    
        # 3. 等待,訊息的回覆
        reply = client.recv(1024)
        print(reply.decode("utf-8"))
    
    # 關閉連線,關閉連線時會向服務端傳送空資料。
    client.close()
    

案例:檔案上傳

  • 服務端

    import socket
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', 8001))  # 127.0.0.1 或 檢視自己區域網本地IP地址
    sock.listen(5)
    
    conn, addr = sock.accept()
    
    # 接收檔案大小
    data = conn.recv(1024)
    total_file_size = int(data.decode('utf-8'))
    
    # 接收檔案內容
    file_object = open('xxx.png', mode='wb')
    recv_size = 0
    while True:
        # 每次最多接收1024位元組
        data = conn.recv(1024)
        file_object.write(data)
        file_object.flush()
    
        recv_size += len(data)
        # 上傳完成
        if recv_size == total_file_size:
            break
    
    # 接收完畢,關閉連線
    conn.close()
    sock.close()
    
    
  • 客戶端

    import time
    import os
    import socket
    
    client = socket.socket()
    client.connect(('127.0.0.1', 8001))
    
    file_path = input("請輸入要上傳的檔案:")
    
    # 先傳送檔案大小
    file_size = os.stat(file_path).st_size
    client.sendall(str(file_size).encode('utf-8'))
    
    print("準備...")
    time.sleep(2)
    print("開始上傳..")
    file_object = open(file_path, mode='rb')
    read_size = 0
    while True:
        chunk = file_object.read(1024) # 每次讀取1024位元組
        client.sendall(chunk)
        read_size += len(chunk)
        if read_size == file_size:
            break
    
    client.close()
    

3. B/S和C/S架構

image

平時在開發或與人溝通時,經常會有人提到b/s和c/s架構,他們是啥意思呢?

  • C/S架構,是Client和Server的簡稱。開發這種架構的程式意味著你即需要開發客戶端也需要開發服務端。

    例如:你電腦的上QQ、百度網盤、釘釘、QQ音樂 等安裝在電腦上的軟體。
    
    服務端:網際網路公司會開發一個程式放在他們的伺服器上,用於給客戶端提供資料支援。
    客戶端:大家在電腦安裝的相關程式,內部會連線服務端進行收發資料並提供 互動和展示的功能。
    
  • B/S架構,是Browser和Server的簡稱。開發這種架構的程式意味著你開發服務端即可,客戶端用使用者電腦上的瀏覽器來代替。

    例如:淘寶、京東等網站。
    
    服務端:網際網路公司開發一個網站,放在他們的伺服器上。
    客戶端:不需要開發,用現成的瀏覽器即可。
    

簡而言之,B/S架構就是開發網站;C/S架構就是開發安裝在電腦的軟體。

總結

  1. 瞭解常見裝置和網路架構。
  2. 掌握常見網路詞彙的意思。
  3. 瞭解B/S和C/S架構的區別。
  4. 基於Python的socket模組實現網路程式設計。

作業

  1. 簡述 二層交換機 & 路由器 & 三層交換機 的作用。
二層交換機:構建區域網並實現區域網內資料的轉發。
路由器:實現跨區域網進行通訊。
三層交換機:具備二層交換機和路由的功能。
  1. 簡述常見詞:IP、子網掩碼、DHCP、公網IP、埠、域名的作用。
IP,本質上是一個32位的二進位制,透過 . 等分為了4組8位二進位制。
子網掩碼,用於指定IP的網路地址和主機地址。
DHCP,網路裝置中的一個服務,用於給接入當前網路的電腦自動設定 IP、子網掩碼、閘道器。
公網IP,一般企業拉專線時會給固定的公網IP,只有具備公網IP才可以被網際網路上的其他電腦訪問。
埠,IP用於表示某臺電腦,埠則表示此電腦上的具體程式。0-65535
域名,與IP構造對應關係,方便使用者記憶。
  1. 實現遠端使用者認證系統。

    客戶端:
        1. 執行程式,連線服務端並獲取服務端傳送的歡迎使用xx系統資訊。
        2. 輸入使用者名稱和密碼,並將使用者名稱和密碼傳送到服務端去校驗。
        3. 登入失敗,重試(Q退出)。
        4. 登入成功,進入系統,提示登入成功
    服務端:
        1. 客戶端連線上服務端,返回 歡迎使用xx系統資訊。
        2. 等待客戶端傳送使用者名稱和密碼進行校驗(使用者名稱和密碼在檔案中)
        3. 登入失敗,返回錯誤資訊。
        4. 登入成功,返回成功提示的內容。
    

    服務端:

     import socket
     import json
     
     # 1.監聽本機的IP和埠
     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     sock.bind(('127.0.0.1', 8001))  # 127.0.0.1 或 檢視自己區域網本地IP地址
     sock.listen(5)
     
     while True:
         # 2.等待,有人來連線(阻塞)
         conn, addr = sock.accept()
     
         # 3.連線成功後立即傳送
         conn.sendall("歡迎使用xx系統".encode("utf-8"))
     
         while True:
             # 3.等待接受資訊
             data = conn.recv(1024)
             if not data:
                 break
             data_string = data.decode("utf-8")
             username, password = data_string.split('|')
     
     
             file_object = open("db.csv", mode='r', encoding='utf-8')
     
             is_success = False
             for line in file_object:
                 user, pwd = line.strip().split(",")
                 if user == username and pwd == password:
                     is_success = True
     
             file_object.close()
     
             if is_success:
                 info = {"status": True, 'msg': "登入成功"}
                 conn.sendall(json.dumps(info).encode("utf-8"))
                 break
             else:
                 info = {"status": False, 'msg': "登入失敗"}
                 conn.sendall(json.dumps(info).encode("utf-8"))
         # 5.關閉與此人的連線
         conn.close()
     
     # 6.停止服務端程式
     sock.close()
    

    客戶端:

     import socket
     import json
     
     client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     client.connect(("127.0.0.1", 8081))
     
     # 2.連線成功後,獲取系統登入資訊
     message = client.recv(1024)
     print(message.decode("utf-8"))
     
     while True:
         user = input("請輸入使用者名稱:")
         pwd = input("請輸入密碼:")
         content = "{}|{}".format(user, pwd)
         client.sendall(content.encode("utf-8"))
     
         reply = client.recv(1024)
         info = json.loads(reply.decode("utf-8"))
         if info['status']:
             print(info['msg'])  # 登入成功
             break
         else:
             print(info['msg'])  # 登入失敗
     # 關閉連線
     client.close()
    

相關文章