• 粘包现象


    udp协议是不存在粘包现象的,因为它文件的传输方式就是面向包的

    tcp协议是有可能出现粘包现象的,它存在粘包的情况有两种:

    a.连续发送小包,如果出现网络延迟现象的话,两次发送的消息会一次性被接收

    b.如果一次性发送的 ,文件过大,一般来说文件一次性传输大小为1500左右,我们定义接收的大小为1024.文件过大的话就会进行切割

    在缓冲区等待发送,有可能会和下一个文件一起被接收.

    面对粘包有两种方式:

    (1)问题的根源在于,接收端不知道发送端将要传送的字节流的长度,所以解决粘包的方法就是围绕,如何让发送端在发送数据前,把自己将要发送的字节流总大小让接收端知晓,然后接收端发一个确认消息给发送端,然后发送端再发送过来后面的真实内容,接收端再来一个死循环接收完所有数据。

    server代码

    import socket,subprocess
    ip_port=('127.0.0.1',8080)
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    s.bind(ip_port)
    s.listen(5)
    
    while True:
        conn,addr=s.accept()
        print('客户端',addr)
        while True:
            msg=conn.recv(1024)
            if not msg:break
            res=subprocess.Popen(msg.decode('utf-8'),shell=True,
                                stdin=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             stdout=subprocess.PIPE)
            err=res.stderr.read()
            if err:
                ret=err
            else:
                ret=res.stdout.read()
            data_length=len(ret)
            conn.send(str(data_length).encode('utf-8'))
            data=conn.recv(1024).decode('utf-8')
            if data == 'recv_ready':
                conn.sendall(ret)
        conn.close()
    
    tcp_server.py
    tcp_server.py

     cilent代码

    import socket,time
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    res=s.connect_ex(('127.0.0.1',8080))
    
    while True:
        msg=input('>>: ').strip()
        if len(msg) == 0:continue
        if msg == 'quit':break
    
        s.send(msg.encode('utf-8'))
        length=int(s.recv(1024).decode('utf-8'))
        s.send('recv_ready'.encode('utf-8'))
        send_size=0
        recv_size=0
        data=b''
        while recv_size < length:
            data+=s.recv(1024)
            recv_size+=len(data)
    
    
        print(data.decode('utf-8'))
    tcp_cilent.py

    (2)解决方案(二):

    通过struck模块将需要发送的内容的长度进行打包,打包成一个4字节长度的数据发送到对端,对端只要取出前4个字节,然后对这四个字节的数据进行解包,接收数据端就知道我们总数据长度是多少,然后同一文件就会进行一次封装.
    server端
    import socket,struct,json
    import subprocess
    phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    
    phone.bind(('127.0.0.1',8080))
    phone.listen(5)
    
    while True:
        conn,addr=phone.accept()
        while True:
            cmd=conn.recv(1024)
            if not cmd:break
            print('cmd: %s' %cmd)
    
            res=subprocess.Popen(cmd.decode('utf-8'),
                                 shell=True,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
            err=res.stderr.read()
            print(err)
            if err:
                back_msg=err
            else:
                back_msg=res.stdout.read()
    
            headers={'data_size':len(back_msg)}
            head_json=json.dumps(headers)
            head_json_bytes=bytes(head_json,encoding='utf-8')
    
            conn.send(struct.pack('i',len(head_json_bytes))) #先发报头的长度
            conn.send(head_json_bytes) #再发报头
            conn.sendall(back_msg) #在发真实的内容
    
        conn.close()
    ctp_server.py

    cilent端口

    import struct,json,socket
    
    ip_port=('127.0.0.1',8080)
    client=socket(AF_INET,SOCK_STREAM)
    client.connect(ip_port)
    
    while True:
        cmd=input('>>: ')
        if not cmd:continue
        client.send(bytes(cmd,encoding='utf-8'))
    
        head=client.recv(4)
        head_json_len=struct.unpack('i',head)[0]
        head_json=json.loads(client.recv(head_json_len).decode('utf-8'))
        data_len=head_json['data_size']
    
        recv_size=0
        recv_data=b''
        while recv_size < data_len:
            recv_data+=client.recv(1024)
            recv_size+=len(recv_data)
    
        #print(recv_data.decode('utf-8'))
        print(recv_data.decode('gbk')) #windows默认gbk编码
    tcp_client.py
  • 相关阅读:
    objectivec随机数
    UITableView中多个UITextField时UITableView的滚动和键盘的隐藏
    objectivec用图片设置backgroundcolor
    SQL代码添加字段
    如何让第三方库暂时不用arc
    快速统计表中的记录总数
    商务报盘英语
    对话:职业健康和安全
    你适合买房还是租房?
    怎样与同事和谐相处
  • 原文地址:https://www.cnblogs.com/lowen107/p/10027806.html
Copyright © 2020-2023  润新知