前缀长度封帧

在每一个数据块之前再加一个用于表示长度的数据,叫做前缀长度封帧

note:多数上层应用自行封帧,所以本章不重要

#!/usr/bin/env python3
#-*- encoding:utf8 -*-

import socket,struct
from argparse import ArgumentParser

header_struct = struct.Struct('!I')

def recvall(sock,length):
    blocks = []
    while length:
        block = sock.recv(length)
        if not block:
            raise EOFError('socket closed with %d bytes left''in this block'.format(length))
        length -= len(block)
        blocks.append(block)
    return b''.join(blocks)

def get_block(sock):
    data = recvall(sock,header_struct.size)
    (blcok_length,) = header_struct.unpack(data)
    return recvall(sock , blcok_length)


def put_block(sock,message):
    block_length = len(message)
    sock.send(header_struct.pack(block_length))
    sock.send(message)

def server(addr):
    sock = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET , socket.SO_REUSEADDR , 1 )
    sock.bind(addr)
    sock.listen(1)
    print('Run this script in another window with "-c" to connect ')
    print('Listening at', sock.getsockname())
    sc,sockname = sock.accept()
    print('Accept connection from ' , sockname)
    sc.shutdown(socket.SHUT_WR)

    while True:
        block = get_block(sc)
        if not block:break
        print('Block says:' , repr(block))
    sc.close()
    sock.close()

def client(addr):
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sock.connect(addr)
    sock.shutdown(socket.SHUT_RD)
    put_block(sock,b'Beautiful is better than ugly')
    put_block(sock,b'Explicit is better than implicit')
    put_block(sock,b'Simple is better than complex')
    sock.close()

if __name__ == "__main__":
    parser = ArgumentParser(description="Transmit & receive blocks over TCP")
    parser.add_argument('hostname',nargs='?',default='127.0.0.1',
                        help='IP address or Hostname(default:%(default)s)')
    parser.add_argument('-c', action='store_true' , help='run as the client')
    parser.add_argument('-p',type=int,metavar='port',default=1060,
                        help='TCP port number(default:%(default)s)')
    args = parser.parse_args()
    function =client if args.c else server
    function((args.hostname,args.p))
原文地址:https://www.cnblogs.com/alben-cisco/p/7087918.html