python學習筆記1.5 異常處理和網絡編程

異常處理

try:
    names[3]
    data["name"]
except KeyError as e:#抓取一個錯誤
    print("沒有這個key", e)
except (err1, err2) as e:#抓取兩個錯誤
    print("列表操作錯誤", e)
except Exception as e:#抓取所有錯誤
    print("出錯了", e)
else:
    print("一切正常")
finally:
    print("無論對錯都執行")

斷言

 assert type(obj.name) is str
print("斷言正確")

Socket網絡編程

  • Socket又稱"套接字",應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求,使主機間或者一臺計算機上的進程間可以通訊。

    • 一些其他協議
      協議	    功能用處	                 端口號	  Python 模塊
      http        網頁訪問                     80       httplib, urllib, xmlrpclib
      smtp        發送郵件                     25       smtplib
      dns         域名/IP地址轉換              53
      ftp         文件傳輸                     20       ftplib, urllib
      ssh         爲網絡服務提供安全性的協議   22
      snmp        簡單網絡管理協議
      icmp ping   互聯網控制報文協議
      dhcp        動態主機配置協議
      ...
      
  • 所有協議本質上都是由:發send和收receive

  • Socket是對以上協議發send和收receive接口的封裝

  • 粘包:服務端連續發送數據是,緩存區裏兩條挨着的數據會黏在一起發送給客戶端

  • 解決辦法:兩次數據發送中間加一次交互

  • OSI七層

    應用
    表示
    會話
    傳輸 TCP/IP 三次握手,四次斷開  1、syn->2、syn/ack->3、ACK  UDP不安全的數據傳輸
    網絡 ip
    數據鏈路 mac
    物理層
    
  • 一個機器(服務器)上可以開65535個端口(port) 通信的實現要通過IP+port

    Nginx 80
    MySQL 3306
    
  • 發送端流程

    import socket
    socket.TCP/IP
    connect(a.ip,a.port)
    socket.send(hello)
    socket.recv()
    socket.close()
    
      - 實例
      	```python
      	import socket
    
      	client = socket.socket()  # 聲明socket類型,同時生成socket連接對象
      	client.connect(("localhost", 9000))
    
      	# client.send(b"Hello World!")#python3裏要轉字節傳輸
      	while True:
      		msg = input(">>:").strip()
      		if len(msg) == 0: continue
      		client.send(msg.encode("utf-8"))
      		data = client.recv(1024)  # 收1024字節
      		print("recv:", data.decode())
      	client.close()
      	```
    
  • 接收端(服務端)

    import socket
    socket.TCP/IP
    listen(ip,port)
    waiting()等
    recv()收
    send()回覆
    
    • 實例
      	server = socket.socket()  # 聲明socket類型,同時生成socket連接對象
      server.bind(("localhost", 9000))  # 綁定到要監聽端口
      server.listen(5)  # 監聽
      print("我要開始等電話了")
      while True:
          conn, addr = server.accept()  # 等電話打進來
          # conn就是客戶端連過來而在服務器端爲其生成的一個連接實例
          print(conn, addr)
          print("電話來了")
          while True:
              data = conn.recv(1024)
              print("recv:", data.decode())
              if not data:
                  print("client has lost...")
              conn.send(data.upper())#服務端最多能發送32M
      
      server.close()
      
  • Socket Families(地址簇)

    socket.AF_UNIX  unix本機進程間通信
    socket.AF_INET ipV4
    socket.AF_INET6 ipV6
    
    Socket Types
    socket.SOCK_STREAM #for tcp
    socket.SOCK_DGRAM #for udp
    socket.SOCK_RAW #原始套接字,普通的套接字無法處理ICMP、IGMP的網絡報文,而SOCK_RAW可以;其次SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由用戶構造IP頭(可以僞造物理攻擊即doc攻擊)。
    

ftp server流程

1、讀取文件
2、檢測文件是否存在
3、打開文件
4、檢測文件大小
5、發文件大小給客戶端
6、等客戶端確認
7、開始邊讀邊發數據
8、發送md5

多任務 - 線程

  • 概念:簡單地說就是操作系統可以同事運行多個任務,如同時聽歌、用word工作、瀏覽器上網

  • 單核CPU執行多任務:操作系統讓任務交替執行,任務1執行0.01s,任務2執行0.01s,任務,3執行0.01s...

    • 並行:真的多任務
    • 併發:假的多任務(時間片輪轉)
  • 線程:

    • 一個程序運行起來之後,一定有一個執行代碼的東西,這個東西就叫做線程

    • python的thread模塊是比較底層的模塊,python的threading模塊對thread做了一些包裝,可以更加方便的被使用

    • 查看正在運行的線程用:threading.enumerate()

    • 當調用Thread的時候,不會創建線程

    • 當調用Thread創建出來的實例對象的start方法的時候,纔會創建線程以及讓個這個線程開始運行

    • 同時創建多個子線程,子線程執行的先後順序是不固定的(隨機的)

    • 如果創建Thread時執行的函數,函數運行結束就意味着這個子線程結束

    • 子線程一定先於主線程結束

    • 創建子線程:

      • 通過指定函數創建子線程
        • 創建帶參數的線程threading.Thread(target=test1, args=(參數,))
        • target:指定將來這個線程去哪個函數執行代碼
        • args:指定將來調用函數的時候傳遞什麼數據過去(args必須是個元組)
      • 通過繼承Thread類創建子線程
    • 多線程共享全局變量:

      • 在一個函數中對全局變量進行修改的時候,是否需要用global進行說明,要看是否對全局變量的指向進行了修改
      • 如果修改了指向,那麼必須用global,如果僅僅是修改了指向的空間中的數據,此時不必使用global
      • 多線程共享全局變量的時候會存在資源競爭
    • 同步

      • 同步就是協同步調,按預定的先後順序運行,如:你說完·我再說
      • 進程、線程同步,可以理解爲進程或線程A和B一塊配合,A執行到一定程度的時候要依靠B的某個結果, 於是停下來,讓B運行;B執行,將結果給A;A再繼續操作
    • 互斥鎖

      • 當多個線程幾乎同時修改某一個共享數據的時候,需要進行同步控制
    • 死鎖

      • 在線程間共享多個資源的時候,如果兩個線程分別佔有一部分資源,並且同時等待對方的資源,就會造成死鎖

      • 避免死鎖

        • 程序設計時要儘量避免(銀行家算法)
        • 添加超時時間

進程、線程、協程對比

  • 進程是資源分配單位
  • 線程是操作系統調度的單位
  • 進程切換需要的資源最大,效率很低
  • 線程切換需要的資源一般,效率一般(當然了在不考慮GIL的情況下)
  • 協程切換任務資源很小,效率高
  • 多進程、多線程根據CPU核數不一樣可能是並行的,但是協程是在一個線程中所以是併發

SocketServer:實現併發處理

SocketServer.TCPServer
SocketServer.UDPServer
SocketServer.UnixStreamServer
SocketServer.UnixDatagramServer
  • 1、你必須自己創建一個請求處理類,並且這個類要繼承BaseRequestHandler,並且還有重寫父親類裏的handler()
  • 2、你必須實例化TCPServer,並且傳遞server ip 和你上面創建的請求處理類,給這個TCPServer
  • 3、調用handle_request()和server_forever()方法
    • server.handle_request()#只處理一個請求
    • server.server_forever()#處理多個請求,永遠執行
  • 4、調用server_close()去關閉這個socket
    • 實例
      	import socketserver
      
      	class MyTCPHandler(socketserver.BaseRequestHandler):
      		'''
      			繼承socketserver,重寫handle方法
      		'''
      
      		def handle(self):
      			while True:
      				try:
      					# self.request是TCP socket 鏈接到客戶端
      					self.data = self.request.recv(1024).strip()
      					print("{} worte:".format(self.client_address[0]))
      					print(self.data)
      					self.request.sendall(self.data.upper())
      				except ConnectionResetError as e:
      					print("err:",e)
      					break
      
      	if __name__ == "__main__":
      		HOST, PORT = "localhost", 9000
      
      		server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)#多線程
      		# server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler)#多進程(linex)
      
      		server.serve_forever()
      

練習:開發一個支持多用戶在線的FTP程序

要求:

    1、用戶加密認證
    2、允許同時多用戶登錄
    3、每個用戶有自己的home目錄,且只能訪問自己的home目錄
    4、對用戶進行磁盤配額,每個用戶的可用空間不同
    5、允許用戶在ftp server上隨意切換目錄
    6、允許用戶查看當前目錄下的文件
    7、允許上傳和下載文件,保證文件的一致性
    8、文件傳輸過程中顯示進度條
    9、附加功能:支持文件斷點續傳
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章