概念
局域網
- 同一局域網內的機器由交換機負責通信,
- 交換機只識別mac地址,交換機可以完成廣播、單播、組播,
- arp協議:通過一臺機器的IP地址獲取到它的mac地址,用到交換機的廣播和單播,
一臺計算機想向同一局域網內的另一個計算機通信必須通過交換機,先向交換機發送自己的IP和mac地址,交換機通過廣播向所有計算機發送資訊,只有對應計算機會應答并向交換機發送自己的mac地址,從而實作同一局域網內的通信,
局域網之間通信
- 局域網之間通信通過路由器,
- 路由器可識別IP地址,并且路由器提供網關IP,同一個局域網的所有機器共享一個網關IP,
- 每個局域網有一個網段,路由器內有路由表,一個網關IP對應一個網段,
IP地址
- IPV4:點分十進制(0.0.0.0 - 255.255.255.255)
- 公網地址:需要申請購買
- 內網地址:保留欄位
- 192.168.0.0 - 192.168.255.255 學校
- 172.16.0.0 - 172.31.255.255 學校
- 10.0.0.0 - 10.255.255.255 公司
- 127.0.0.1為本地回環地址,通常用于測驗,
- 查看自己的IP地址:ipconfig(Windows)/ifconfig(Mac/Linix)
- 子網掩碼:為一個IP地址,用于判斷兩臺機器在不在同一局域網內,采用二進制相與的方法,當相與結果相同則在同一局域網內,
網路開發架構
C/S架構
-
需要安裝才可使用
-
client:客戶端,server:服務端
-
離線可使用,功能更完善,安全性更高
# 基于tcp # server端 import socket sk = socket.socket() sk.bind(('127.0.0.1', 5002)) # 5002是埠 # 打開監聽模式 sk.listen() # 建立連接,conn是連接,addr是連接的地址 conn, addr = sk.accept() # 發送資訊 conn.send(b'Hello, I am server') # 最多接收1024位元組 msg = conn.recv(1024) print(msg) print(addr) conn.close() # 關閉連接 sk.close() # 關閉整個服務 ######################################### # client端 import socket sk = socket.socket() # 建立連接 sk.connect(('127.0.0.1', 5002)) # 接收資訊 msg = sk.recv(1024) print(msg) # 發送資訊 sk.send(b'Hello, I am client') sk.close() # 關閉連接
B/S架構
- 不用安裝就可使用
- browser:瀏覽器,server:服務端
- 其中B/S也是C/S架構的一種
OSI五層協議
- 應用層:應用程式(python)
- 傳輸層:port,udp/tcp,四層路由器,四層交換機
- 網路層:ipv4/ipv6,路由器,三層交換機
- 資料鏈路層:mac,arp協議,網卡,二層交換機
- 物理層
tcp和udp
-
tcp:需要建立連接才能通信
- 占用連接,可靠(資訊不會丟失),實時性高
- 建立連接:三次握手(建立全雙工通信)
- 斷開連接:四次揮手
-
udp:不需要建立連接就可以通信
-
不占用連接,不可靠(訊息因為網路不穩定丟失)
-
需要用到
.recvfrom(可接收資訊和IP)和.sendto(發送資訊需附帶IP地址),# server端 # 一服務端對多客戶端通信 # 服務端不用主動退出,由客戶端收發訊息進行退出 import socket sk = socket.socket(type = socket.SOCK_DGRAM) # 默認引數是tcp,此引數為udp sk.bind(('127.0.0.1', 5002)) while True: # 不能先發送,因為不知道接收端地址資訊,只能等待接收,并且必須接收到客戶端的地址 msg_r, addr = sk.recvfrom(1024) print(addr) print(msg_r.decode('UTF-8')) msg_s = input(">>>") sk.sendto(msg_s.encode('UTF-8'), addr) ################################################ # client端 import socket sk = socket.socket(type = socket.SOCK_DGRAM) # 傳入服務端地址 server = ('127.0.0.1', 5002) while True: msg_s = input(">>>") sk.sendto(msg_s.encode('UTF-8'), server) if msg_s == "拜拜": break # 接收服務端的資訊,由于知道服務端地址所以不需要recvfrom msg_r = sk.recv(1024) if msg_r.decode('UTF-8') == "拜拜": break print(msg_r.decode('UTF-8'))
-
-
粘包現象
-
只出現在tcp協議中,因為tcp協議的多條資訊之間沒有邊界,并且有優化演算法,
tcp協議發送資料大小沒有上限,當資料過大時會將資料進行拆分,所以多條訊息之間沒有邊界 -
發送端:兩條訊息都很短,發送間隔時間也非常短導致,
-
接收端:多條訊息由于沒有及時接收,接收端快取堆在一起導致,
-
解決辦法:設定邊界
自定義協議:發送端統計長度,每次將長度固定為n位元組發送# server端同時發送兩條訊息 msg_s1 = input(">>>") msg_s2 =input(">>>") lens = str(len(msg_s1)) # 統計msg_s1的長度,ziff傳入資料應為str,所以要轉成str len = lens.zfill(4) # 將收集到的長度大小統一擴至4位元組,例如msg_s1長度為6位元組,則為0006 conn.send(len.encode('UTF-8')) # 將長度資訊發送出去 conn.send(msg_s1.encode('UTF-8')) conn.send(msg_s2.encode('UTF-8')) # clien端接收 len = int(sk.recv(4).decode('UTF-8')) # 接收長度資訊 msg_r1 = sk.recv(len) msg_r2 = sk.recv(1024) print(msg_r2.decode('UTF-8')) print(msg_r1.decode('UTF-8')) ############################################################### # struct方法 # server端同時發送兩條訊息 msg_s1 = input(">>>") msg_s2 =input(">>>") lens_byte = struct.pack('i', len(msg_s1)) # 可以將資料轉成固定4位元組 conn.send(lens_byte) conn.send(msg_s1.encode('UTF-8')) conn.send(msg_s2.encode('UTF-8')) # clien端接收 lens_byte = sk.recv(4) len = struct.unpack('i', lens_byte)[0] # unpack回傳值為元組,第一位即為長度資訊 msg_r1 = sk.recv(len) msg_r2 = sk.recv(1024) print(msg_r1.decode('UTF-8')) print(msg_r2.decode('UTF-8'))
-
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/175705.html
標籤:Python
