一 .UDP不黏包 會丟包html
1. 不黏包 丟包算法
UDP(user datagram protocol,用戶數據報協議)是無鏈接的,面向消息的,提供高效率服務。
不會使用塊的合併優化算法,, 因爲UDP支持的是一對多的模式,因此接收端的skbuff(套接字緩衝區)
採用了鏈式結構來記錄每個到達的UDP包,在每一個UDP包中就有了消息頭(消息來源地址,端口等信息)
,這樣,對於接收端來講,就容易進行區分處理了。 即面向消息的通訊是有消息保護邊界的。
對於空消息:tcp是基於數據流的,因而收發的消息不能爲空,這就須要在客戶端和服務端都添加空消息的處理機制,
防止程序卡住,而udp是基於數據報的,即使是你輸入的是空內容(直接回車),也能夠被髮送,udp協議會幫你封裝上消息頭髮送過去。
不可靠不黏包的udp協議:udp的recvfrom是阻塞的,一個recvfrom(x)必須對惟一一個sendinto(y)
,收完了x個字節的數據就算完成,如果y;x數據就丟失,這意味着udp根本不會粘包,可是會丟數據,不可靠。
用UDP協議發送時,用sendto函數最大能發送數據的長度爲:65535- IP頭(20) – UDP頭(8)=65507字節。
用sendto函數發送數據時,若是發送數據長度大於該值,則函數會返回錯誤。(丟棄這個包,不進行發送)
2 .基於udp協議實現不黏包 丟包shell
基於UDP先製做一個遠程執行命令的程序(命令ls -l ; lllllll ; pwd)socket
client1 from socket import * ip_port=('127.0.0.1',9000) client=socket(AF_INET,SOCK_DGRAM) while True: msg=input('>>: ').strip() client.sendto(msg.encode('utf-8'),ip_port) err,addr=client.recvfrom(1024) out,addr=client.recvfrom(1024) if err: print('error : %s'%err.decode('utf-8'),end='') if out: print(out.decode('utf-8'), end='')
server1 from socket import * import subprocess ip_port=('127.0.0.1',9000) server=socket(AF_INET,SOCK_DGRAM) server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) server.bind(ip_port) while True: #收消息 cmd,addr=server.recvfrom(1024) #邏輯處理 res=subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=subprocess.PIPE,stdin=subprocess.PIPE,stdout=subprocess.PIPE) stderr=res.stderr.read() stdout=res.stdout.read() #發消息 server.sendto(stderr,addr) server.sendto(stdout,addr) server.close()
server1 # UDP # udp 永遠 不會黏包 #只有TCP有粘包現象,UDP永遠不會粘包 # 可是會丟包 # https://www.cnblogs.com/Eva-J/articles/8244551.html # https://www.cnblogs.com/Eva-J/p/7277026.html # UDP不會發生黏包 #_*_coding:utf-8_*_ from socket import * import subprocess ip_port=('127.0.0.1',9000) bufsize=1024 udp_server=socket(AF_INET,SOCK_DGRAM) udp_server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) udp_server.bind(ip_port) while True: #收消息 cmd,addr=udp_server.recvfrom(bufsize) print('用戶命令----->',cmd) #邏輯處理 res=subprocess.Popen(cmd.decode('utf-8'),shell=True,stderr=subprocess.PIPE,stdin=subprocess.PIPE,stdout=subprocess.PIPE) stderr=res.stderr.read() stdout=res.stdout.read() #發消息 udp_server.sendto(stderr,addr) udp_server.sendto(stdout,addr) udp_server.close()