socket之粘包

server端代码:

import socket
import subprocess
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8848))
server.listen(5)
conn,addr = server.accept()
while 1:
    try:
        #接收数据
        from_client_date = conn.recv(1024)
        print(f'接收客户端的数据是:{from_client_date.decode("utf-8")}')
        cmd = subprocess.Popen(
            from_client_date.decode('utf-8'),
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,)
        #返回数据
        result = cmd.stdout.read() + cmd.stderr.read()
        conn.send(result)
    except ConnectionResetError:
        break
conn.close()
server.close()

client端代码:

import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8848))
while 1:
    #发送数据
    date_input = input('>>>>>>>:').strip()
    if date_input.upper() == 'Q':
        client.send('q'.encode('utf-8'))
        break
    client.send(date_input.encode('utf-8'))
    # 接收数据
    server_date = client.recv(1024)
    print(f'服务端的数据是{server_date.decode("gbk")}')
client.close()

当我输入dir的时候可以接受全部返回的数据,我recv接受的是1024,如果大于1024呢?剩下的数据怎么办?

接下来我继续输入ipconfig,实际上是没有接收完整的,数据大于1024个字节
在这里插入图片描述
这张图可以看到和我cmd里面是比较时接收不完整
在这里插入图片描述
接下来我继续输入dir,发现未接收到的剩余数据给我返回回来了
在这里插入图片描述
我最后一次输入的dir产生的数据一点没收,收到的是我上一次残留的,这就是粘包现象,粘包的根本现象就是缓冲区,下面来说一下缓冲区:
客户端有两个缓冲区:一个是输出缓冲区,一个是接收缓冲区,当你数据发送过去之后recv会处于一个阻塞状态:有数据就立马拿,所以就导致我们输入dir后收到的却是ipconfig残留的数据,画个图理解一下:
在这里插入图片描述
为什么产生黏包:
recv的时候 发送的总数量超过我设置的recv数量的时候 第二次发送的数据还没到我recv之前 数据就已经取完了,有一个时间差在里面,如果我用sleep等待一下呢?
在这里插入图片描述
最后我再输入dir就可以全部接收到了,但不建议这么做,太影响非效率,还有的同学说可以扩大recv的上限,这不是解决问题的根本原因,这些数据都会放在内存中在这里插入图片描述
不光recv会粘包,send也会粘包:

client端:

import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(('127.0.0.1',8848))
client.send(b'hello')
client.send(b'word')
client.close()

server端:

import socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('127.0.0.1',8848))
server.listen(5)
conn,addr = server.accept()
f1 = conn.recv(1024)
print(f'1:{f1}')
f2 = conn.recv(1024)
print(f'2:{f2}')
conn.close()
server.close()
最后服务端打印结果:
1:b'helloword'
2:b''

总结:
send也可能会发生粘包现象(连续send少量的数据发到输出缓冲区 由于缓冲区的机制,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,这取决于当时的网络情况、当前线程是否空闲等诸多因素,不由程序员控制。)
send产生黏包:连续发送多个少量数据 数据会等着一起发送

解决粘包的问题后续更新…

猜你喜欢

转载自blog.csdn.net/qq_39253370/article/details/103411089