網路程式設計(三)
阿新 • • 發佈:2022-04-18
網路程式設計
- UDP協議
- UDP協議實戰
- 作業系統的發展史
- 多道技術
- 程序理論
UDP協議
import socket # 匯入socket模組 server = socket.socket(type=socket.SOCK_DGRAM) # 自己指定UDP協議(預設是TCP協議) server.bind(('127.0.0.1', 8080)) # 繫結一個固定的地址(IP與埠號) msg, addr = server.recvfrom(1024) # 接收客戶端返回的 print('msg>>>:', msg.decode('utf8')) # 解碼操作 print('addr>>>:', addr) # 列印客戶端的地址 server.sendto(b'hello baby', addr) # 回覆客戶端的訊息 import socket # 匯入模組 client = socket.socket(type=socket.SOCK_DGRAM) server_addr = ('127.0.0.1', 8080) # 查詢通訊錄 client.sendto(b'hello server baby', server_addr) # 接收服務端的訊息 msg, addr = client.recvfrom(1024) print('msg>>>:', msg.decode('utf8')) print('addr>>>:', addr)
UDP協議實操
# 服務端 import socket server = socket.socket(type=socket.SOCK_DGRAM) server.bind(('127.0.0.1', 8080)) while True: msg, addr = server.recvfrom(1024) print(addr) print(msg.decode('utf8')) back_msg = input('請回復訊息>>>:').strip() server.sendto(back_msg.encode('utf8'), addr) # 客戶端1 import socket client = socket.socket(type=socket.SOCK_DGRAM) server_addr = ('127.0.0.1', 8080) while True: msg = input('請輸入想要聊天的內容>>>:').strip() msg = '來自客戶端1的訊息:%s' % msg client.sendto(msg.encode('utf8'), server_addr) msg, addr = client.recvfrom(1024) print(msg.decode('utf8'), addr) # 客戶端2 import socket client = socket.socket(type=socket.SOCK_DGRAM) server_addr = ('127.0.0.1', 8080) while True: msg = input('請輸入想要聊天的內容>>>:').strip() msg = '來自客戶端2的訊息:%s' % msg client.sendto(msg.encode('utf8'), server_addr) msg, addr = client.recvfrom(1024) print(msg.decode('utf8'), addr)
由以上可知一個服務端可以處理多個客戶端,但是它們兩個是按照序列執行,就是一定要等到伺服器接收到了客戶端1的返回值才會為客戶端2提供服務
作業系統的發展史
1.穿孔卡片
優勢:一個人獨佔電腦
劣勢:CPU利用率極低
2.聯機批處理系統
一次性可以錄入多個使用者指令、縮短了CPU等待的時間、提高了CPU的利用率
3.離線批處理系統
是現代計算機核心部件的雛形、提高CPU的利用率
# 總結:作業系統的發展史其實就是提升CPU利用率的過程
多道技術
前提:計算機都是單核(一個CPU)的情況下
序列:多個任務排隊執行,總耗時就是多個任務完整時間疊加 多道:利用空閒提前準備,縮短總的執行時間並且還能提高CPU利用率 eg:做飯需要30min 洗衣需要50min 燒水需要20min 序列總共需要耗時:30min + 50min + 20min 多道總共需要耗時:50min # 多道技術 1.空間上的複用:多個任務公用一套計算機硬體 2.時間上的複用:切換+儲存狀態 ps:CPU在兩種情況下會被拿走 1.程式遇到IO操作,CPU會自動切走執行其它程式 2.程式長時間佔用CPU,系統發現之後也會強行切走CPU,保證其它程式也能使用
程序理論
程式:一堆沒有被執行的程式碼(死的)
程序:正在執行的程式(活的)
# 為了更加精確的描述出一些實際狀態才有了程序的概念
# 程序排程演算法發展史
1.先來先服務
對短作業任務不太友好
2.短作業優先
多長作業任務不太友好
3.時間片輪轉法與多級反饋佇列
時間片輪轉法:先公平的將CPU分給每個人執行
多級反饋佇列:根據作業長短的不同再合理分配CPU執行時間
'''目的就是為了能夠讓單核的計算機也能夠做到執行多個程式'''
重要概念
# 併發:看上去像同時在執行就可以稱之為是併發(讓CPU在多個程式之間利用多道技術來回切換+儲存狀態)
# 並行:必須同一時間同時執行才可以稱之為並行。
ps:單核計算機能夠實現併發,但是不能實現並行,想要實現並行就必須要有多個CPU
# 高併發與高並行
高併發:我們寫的軟體可以支援1個億的併發量,一個億的使用者來了之後都可以感覺到自己被服務著
高並行:我們寫的軟體可以支援1個億的並行量,上述話語的言外之意是計算機有一億個CPU
# 同步與非同步
同步:提交完任務之後原地等待任務的返回結果 期間不做任何事情
非同步:提交完任務之後不願地等待任務的結果 直接去做其他事情 有結果自動提醒
# 阻塞與非阻塞
瞭解阻塞與非阻塞之前要先搞清楚程序三狀態圖:
就緒態:程式進入執行狀態之前肯定要處於就緒態
執行態:程式被CPU執行著
阻塞態:程式執行過程中有IO操作
阻塞:阻塞態
非阻塞:就緒態、執行態
ps:如果想要儘可能的執行程式執行效率,就要想辦法讓我們的程式一種處於就緒狀和執行狀(不要有IO操作)
同步非同步與阻塞非阻塞的組合
同步非同步:用來描述任務的提交方式
阻塞非阻塞:用來描述任務的執行狀態
# 上述兩組屬於兩個不同概念 但是可以結合
同步阻塞:銀行排隊辦理業務 期間不做任何事
同步非阻塞:銀行排隊辦理業務 期間喝水吃東西 但是人還在佇列中
非同步阻塞:在椅子上坐著 但是不做任何事
非同步非阻塞:在椅子上坐著 期間喝水吃東西辦公 (程式執行的極致)
作業講解
編寫一個cs架構的軟體
就兩個功能
一個視訊下載:從服務端下載視訊
一個視訊上傳:從客戶端上傳視訊
# 服務端
import socket
import json
import struct
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)
sock, addr = server.accept()
# 1.接收固定長度的報頭
header = sock.recv(4)
# 2.解析出字典的長度
dict_len = struct.unpack('i', header)[0]
# 3.接收字典資料
dict_bytes = sock.recv(dict_len)
dict_data = json.loads(dict_bytes)
# 4.接收真實資料
recv_size = 0
total_size = dict_data.get('file_size')
file_name = dict_data.get('file_name')
# 5.檔案操作
with open(file_name, 'wb') as f:
while recv_size < total_size:
data = sock.recv(1024)
f.write(data)
recv_size += len(data)
# 客戶端
import socket
import os
import json
import struct
client = socket.socket()
client.connect(('127.0.0.1', 8080))
movie_dir_path = r'/Users/jiboyuan/Desktop/直播課/python基礎day33/視訊'
while True:
# 1.迴圈展示出需要上傳的電影列表
movie_name_list = os.listdir(movie_dir_path)
for i, movie_name in enumerate(movie_name_list, start=1):
print(i, movie_name)
choice = input('請選擇您想要上傳的電影編號>>>:').strip()
if not choice.isdigit():
continue
choice = int(choice)
if choice not in range(1, len(movie_name_list) + 1):
print('請輸入正確的編號')
continue
# 2.獲取電影名字
target_movie_name = movie_name_list[choice - 1]
# 3.拼接電影路徑
movie_path = os.path.join(movie_dir_path, target_movie_name)
# 4.製作字典資料
movie_dict = {
'file_name': target_movie_name,
'file_desc': '請及時補充營養',
'file_size': os.path.getsize(movie_path)
}
movie_dict_json = json.dumps(movie_dict)
movie_dict_len = len(movie_dict_json.encode('utf8'))
# 5.製作字典報頭
dict_header = struct.pack('i', movie_dict_len)
# 6.傳送字典報頭
client.send(dict_header)
# 7.傳送字典資料
client.send(movie_dict_json.encode('utf8'))
# 8.傳送真實資料
with open(movie_path,'rb') as f:
for line in f:
client.send(line)