tcp黏包问题与udp为什么不黏包

时间:2021-10-25 09:37:23

  1.先说下subprocess模块的用法,为了举个黏包的例子

# 通过一个例子 来认识网络编程中的一个重要的概念
    # 所有的客户端执行server端下发的指令,执行完毕后,客户端将执行结果给返回给服务端


import subprocess   # 这个模块其实并不好用,这里为了举例子。调用操作系统的命令模块


res = subprocess.Popen('dir', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 执行dir命令,并将标准输出和错误内容装到了管道中
print('stdout : ', res.stdout.read().decode('gbk')) # 从管道中获取控制台的内容,windows控制台执行完毕后,得到的是bytes类型的,需要解码成gbk才可不乱码显示,windows控制台返回的是gbk的,所以这里要gbk解码
print('stderror: ', res.stderr.read().decode('gbk'))

  2.写一个tcp的server端和client,模拟黏包的现象,tcp端发送windows的命令给client,client接收后执行该命令后,将控制台返回的内容传输到server端

  tcpserver.py

# 通过一个例子 来认识网络编程中的一个重要的概念
    # 所有的客户端执行server端下发的指令,执行完毕后,客户端将执行结果给返回给服务端
    # 基于tcp实现远程执行命令

    # 在server下发windows操作系统命令给client,client执行完毕后返回给sercer

# 出现了黏包现象
    # 数据乱了,数据没有接收完,下次接收接收到了未接收到的数据等现象

# tcp不会丢包,会黏包。
    # 当传输的包很大的时候,tcp协议会将其拆分开进行传输。

import socket

sk = socket.socket()

sk.bind(('127.0.0.1', 8080))

sk.listen()

conn, addr = sk.accept()

while True:
    cmd = input('输入想要客户端windows系统想要执行的命令:')
    conn.send(cmd.encode('utf-8'))
    msg = conn.recv(1024).decode('utf-8')
    print(msg)

conn.close()
sk.close()

  tcpclient.py

# client接收服务端命令

import socket
import subprocess

sk = socket.socket()

sk.connect(('127.0.0.1', 8080))

while True:
    cmd = sk.recv(1024).decode('utf-8')
    res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout = 'stdout : ' + res.stdout.read().decode('gbk')
    stderr = 'stderr : ' + res.stderr.read().decode('gbk')
    #print(stdout)
    #print(stderr)
    # res.stdout.read() 为cmd命令执行后返回的结果,返回的是bytes类型数据
    sk.send(stdout.encode('utf-8'))
    sk.send(stderr.encode('utf-8'))

sk.close()

 

  3.udp不黏包,但会丢包例子,与上类似

  udpserver.py

# 测试结果,udp不会黏包,但udp会丢包,数据发送出去后,一旦另一端接收的缓存不够大,而发送的数据很大时,未接收的数据,会丢弃掉。同时udp大了缓存限制会丢弃包

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)

#sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) # 避免服务重启的时候报address already in use。加上这个解决
sk.bind(('127.0.0.1', 8081))

msg, addr = sk.recvfrom(1024)

while True:
    cmd = input('输入想要客户端windows系统想要执行的命令:')
    if cmd == 'q':
        break
    sk.sendto(cmd.encode('utf-8'), addr)
    msg, addr = sk.recvfrom(1024)
    print(msg.decode('utf-8'))

sk.close()

  udpclient.py

# client接收服务端命令

import socket
import subprocess

sk = socket.socket(type=socket.SOCK_DGRAM)

ip_port = ('127.0.0.1', 8081)
sk.sendto(b'hello', ip_port)

while True:
    cmd, addr= sk.recvfrom(1024)
    res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout = 'stdout : ' + res.stdout.read().decode('gbk')
    stderr = 'stderr : ' + res.stderr.read().decode('gbk')
    #print(stdout)
    #print(stderr)
    # res.stdout.read() 为cmd命令执行后返回的结果,返回的是bytes类型数据
    sk.sendto(stdout.encode('utf-8'), ip_port)
    sk.sendto(stderr.encode('utf-8'), ip_port)

sk.close()

 

  4.tcp为什么会黏包

tcp黏包问题与udp为什么不黏包

  黏包是这样出现的

tcp黏包问题与udp为什么不黏包

  tcp的拆包机制是类似这样的

tcp黏包问题与udp为什么不黏包

 

  5.udp为什么不会黏包

tcp黏包问题与udp为什么不黏包

tcp黏包问题与udp为什么不黏包