五. 網絡編程(UDP 不黏包)

一 .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()
相關文章
相關標籤/搜索