1. 程式人生 > >前綴長度封幀

前綴長度封幀

shutdown cti error not closed pan another server 之前

在每一個數據塊之前再加一個用於表示長度的數據,叫做前綴長度封幀

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,bBeautiful is better than ugly) put_block(sock,bExplicit is better than implicit) put_block(sock,bSimple 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))

前綴長度封幀