tcp協議傳輸數據存在粘包現象,udp協議不存在粘包協議。python
1.發生在發送端的粘包web
因爲兩個數據的發送時間間隔短+數據的長度小,因此由tcp協議的優化機制將兩條信息做爲一條信息發送出去了,是爲了減小tcp協議中的「確認收到」的網絡延遲時間緩存
2.在接收端的粘包網絡
因爲tcp協議中所傳輸的數據無邊界,因此來不及接收的多條數據會在接收方的內核的緩存端黏在一塊兒併發
3.本質: 接收信息的邊界不清晰app
1.自定義協議1:dom
a.首先發送報頭異步
報頭長度4個字節
內容是 即將發送的報文的字節長度
struct模塊socket
b.再發送報文tcp
2.自定義協議2
專門用來作文件發送的協議
1.三次握手
三次握手的過程在代碼中是由accept和connect共同完成的,具體的細節再socket中沒有體現出來
2.四次揮手
io模型種類:
server端同時與多個client客戶端之間的聊天:
socket的非阻塞io模型 + io多路複用實現的
雖然非阻塞,提升了CPU的利用率,可是耗費CPU作了不少無用功
# server.py import socket sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.setblocking(False) # 非阻塞,setblocking()的參數爲False時,表示非阻塞,若是參數不寫,默認爲True。 sk.listen() conn_l = [] del_l = [] while True: try: conn,addr = sk.accept() # 阻塞,直到有一個客戶端來連我 print(conn) conn_l.append(conn) except BlockingIOError: for c in conn_l: try: msg = c.recv(1024).decode('utf-8') if not msg: del_l.append(c) continue print('-->',[msg]) c.send(msg.upper().encode('utf-8')) except BlockingIOError:pass for c in del_l: conn_l.remove(c) del_l.clear() sk.close() # client.py import time import socket sk = socket.socket() sk.connect(('127.0.0.1',9000)) for i in range(30): sk.send(b'zhangsan') msg = sk.recv(1024) print(msg) time.sleep(0.2) sk.close()
socketserver模塊解決了socket的阻塞問題,直接實現tcp協議可併發的server端
# server.py import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): # 自動觸發了handle方法,而且self.request == conn msg = self.request.recv(1024).decode('utf-8') self.request.send('1'.encode('utf-8')) msg = self.request.recv(1024).decode('utf-8') self.request.send('2'.encode('utf-8')) msg = self.request.recv(1024).decode('utf-8') self.request.send('3'.encode('utf-8')) server = socketserver.ThreadingTCPServer(('127.0.0.1',9000),Myserver) server.serve_forever() # client.py import socket import time sk = socket.socket() sk.connect(('127.0.0.1',9000)) for i in range(3): sk.send(b'hello,yuan') msg = sk.recv(1024) print(msg) time.sleep(1) sk.close()
客戶端是提供給 用戶使用的 —— 登錄驗證
你的用戶 就能看到你的client端源碼了,用戶就不須要本身寫客戶端了
客戶端是提供給 機器使用的 —— 驗證客戶端的合法性
防止非法用戶進入服務端竊取內部重要信息
# server.py import os import hashlib import socket def get_md5(secret_key,randseq): md5 = hashlib.md5(secret_key) md5.update(randseq) res = md5.hexdigest() return res def chat(conn): while True: msg = conn.recv(1024).decode('utf-8') print(msg) conn.send(msg.upper().encode('utf-8')) sk = socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() secret_key = b'names' while True: conn,addr = sk.accept() randseq = os.urandom(32) conn.send(randseq) md5code = get_md5(secret_key,randseq) ret = conn.recv(32).decode('utf-8') print(ret) if ret == md5code: print('是合法的客戶端') chat(conn) else: print('不是合法的客戶端') conn.close() sk.close() # client.py import hashlib import socket import time def get_md5(secret_key,randseq): md5 = hashlib.md5(secret_key) md5.update(randseq) res = md5.hexdigest() return res def chat(sk): while True: sk.send(b'hello') msg = sk.recv(1024).decode('utf-8') print(msg) time.sleep(0.5) sk = socket.socket() sk.connect(('127.0.0.1',9000)) secret_key = b'names' randseq = sk.recv(32) md5code = get_md5(secret_key,randseq) sk.send(md5code.encode('utf-8')) chat(sk) sk.close()