31 黏包现象

主要内容:

1. 执行命令 :

  在python中去调用操作系统的命令  引入新的模块  : subprocess

import subprocess
r = subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# subprocess.Popen(cmd,shell=True,subprocess.stdout,subprocess.stderr)
# cmd : 代表系统命令
# shell = True   代表这条命令是 系统命令,告诉操作系统,将cmd当成系统命令去执行
# stdout   是执行完系统命令之后,用于保存结果的一个管道
# stderr   是执行完系统命令之后,用于保存错误结果的一个管道
print(r.stdout.read().decode('gbk'))
print(r.stderr.read().decode('gbk'))

  用subprocess实现,客户端发送要执行的命令, 服务器执行,执行完结果返回客户端, 客户端拿到结果后呈现在用户眼前.

  服务器端的代码:

import socket
import subprocess
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()
conn, addr = sk.accept()
ret = conn.recv(1024).decode('utf-8')
r = subprocess.Popen(ret, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout = r.stdout.read()
stderr = r.stderr.read()
if stdout:
    conn.send(stdout)
else:
    conn.send(stderr)
conn.close()
sk.close()

  客户端的代码:

import socket
import subprocess
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
cmd = input('请用户输入要执行的操作系统的命令:')
sk.send(cmd.encode('utf-8'))
ret = sk.recv(1024).decode('gbk')    # 操作系统中的编码为gbk
print(ret)
sk.close()

2. 黏包问题 :在发送端发送数据,接收端不知道应该如何去接收,造成的一种数据紊乱的现象.

  a :tcp出现黏包的代码:

    服务器端:

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8888))
sk.listen()
conn,addr = sk.accept()
conn.send(b'hello')
conn.send(b'world')
conn.close()
sk.close()

  客户端:

import socket
sk = socket.socket()
sk.connect_ex(('127.0.0.1',8888))
msg1 = sk.recv(1024)
print('msg1:',msg1)
msg2 = sk.recv(1024)
print('msg2:',msg2)
sk.close()

  b : udp不会出现黏包现象:代码:

    服务器端:

import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1',8888))
while 1:
    msg1 = sk.recvfrom(5)
    print('msg1:',msg1)

    msg2 = sk.recvfrom(1024)
    print('msg2:',msg2)
sk.close()

  客户端:

import socket
sk = socket.socket(type=socket.SOCK_DGRAM)
while 1:
    sk.sendto(b'hello',('127.0.0.1',8888))
    sk.sendto(b'world',('127.0.0.1',8888))
sk.close()

    c :  tcp协议中,出现两种黏包现象 : 合包机制和拆包机制

  合包机制的过程:

    过程一 : 发送方引起的黏包是由于tcp协议本身引起的, tcp为了提高自己的效率,发送方往往要收集足够多的数据后才发送一个tcp段.

    过程二 : 若连续几次send的数据都比较小,通常tcp会把这些数据打包合成一个tcp后一次性发送过去,这样接收方就收到了黏包数据.

  拆包机制的过程:

    在发送端,因为受到网卡的mtu限制,会将大的超过mtu限制的数据,进行拆分,拆分成多个小的数据,进行传输,当传输到目标主机的操作系统时,会          重新将多个小的数据合成原来的数据.

    当发送端缓冲区的长度大于网卡的MTU时,tcp会将这次发送的数据拆成几个数据包发送出去。
    MTU是Maximum Transmission Unit的缩写。意思是网络上传送的最大数据包。MTU的单位是字节。 大部分网络设备的MTU都是1500。如果        本机的MTU比网关的MTU大,大的数据包就会被拆开来传送,这样会产生很多数据包碎片,增加丢包率,降低网络速度。

3 .  使用udp协议发送数据, 一次收发数据究竟多少合适:

  1): udp不会发生黏包 , udp协议本层对一次收发数据大小的限制是:

    65535 - ip包头(20) - udp包头(8) = 65507

  2): 站在数据链路层, 因为网卡的mtu一般被限制在了1500,所以对于数据链路层来说,收发数据的大小的限制 :

    1500 - ip包头(20) - udp包头(8) = 1472

原文地址:https://www.cnblogs.com/gyh412724/p/9475532.html