framing:
如何分割消息,使得接收方能够识别消息的开始,由于传递给sendall()的数据可能在实际网络传输的时候被分割成多个数据包,接收消息的程序可能需要进行多个recv()调用才能读取完整的消息。
关于framing需要考虑这样的问题:
接收方合适最终停止调用recv()才是安全的,整个消息或数据合适才能完整无缺的传达?合适才能将接收到的信息作为一个整体来解析或处理?
模式一,
发送方循环不断的发送数据,知道所有的数据都被传递给sendall()为止,然后使用close()关闭套接字,接收方只需要不断地调用recv(),直到recv()最后返回一个空格字符为止。
#!/usr/bin/env python3 #-*- encoding:utf8 -*- import socket from argparse import ArgumentParser def server(address): sock = socket.socket(socket.AF_INET , socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET , socket.SO_REUSEADDR , 1) sock.bind(address) sock.listen(1) print('Run this script in another window with "-c" to connect') print('listening at' , sock.getsockname()) sc,sockname = sock.accept() print('Accepted connection from ' , sockname) sc.shutdown(socket.SHUT_WR) message = b'' while True: more = sc.recv(8192) if not more: print('Receive None!') break print('Receive {} Bytes'.format(len(more))) message += more print('Message: ') print(message.decode()) sc.close() sock.close() def client(address): sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.connect(address) sock.shutdown(socket.SHUT_RD) sock.sendall(b'Beautiful is better than ugly. ') sock.sendall(b'Explicit is better than implicit. ') sock.sendall(b'Simple is better than complex. ') sock.close() if __name__ == "__main__": parser = ArgumentParser(description='Transmit and receive a data stream') parser.add_argument('hostname' , nargs='?' , default='127.0.0.1', help='IP 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))