要实现的是TCP是一个字节流。从TCP获得的保证是发送的字节将以相同的顺序到达。如果字节流表示一系列命令,则无法保证字节将以与您发送的内容对齐的块形式到达。
你可以发送:“execute”,“command”
接收“e”“xecuteco”“mmand”。在
(是的,这是极不可能的,而接收“executecommand”则极有可能,因为nagle算法,但我离题了。关键在于,为了编写健壮的代码,您不必假设TCP如何将数据分解成碎片)
因此,您需要决定的第一件事是如何将请求字节流划分为请求,以及如何将响应字节流划分为响应。在请求内部,您需要决定其内部结构。在
假设您决定请求如下所示:
“动词param1 param2…paramN\n”
即:请求是一个非换行字节序列,后跟一个换行符
请求由一个初始动词(非空格字符)后跟零个或多个参数组成
由于协议本身现在在TCP上有一个附加层,所以最好使用抽象来编写它。类似于:class Request(object):
def __init__(self, verb, *args):
self.verb = verb
self.args = [str(x) for x in args]
class Client(object):
def __init__(self, sock):
self.sock = sock
self.rxbuf = ''
def send_request(self, req):
req_str = req.verb
if req.args:
req_str += ' ' + ' '.join(req.args)
req_str += '\n'
self.sock.sendall(req_str.encode("utf-8"))
class Server(object):
def __init__(self, sock):
self.sock = sock
self.rxbuf = ''
def read_request(self):
while True:
s = self.rxbuf.split('\n', 1)
if len(s) == 2:
req_str = s[0]
self.rxbuf = s[1]
req_lst = req_str.split(' ')
return Request(req_lst[0], *req_lst[1:])
data = self.sock.recv(BUF_SIZE).decode("utf-8")
self.rxbuf += data
当然,这必须由一个决定来补充,即响应的外观如何,以及如何将传入的字节流描述为一系列响应。我想用这个代码说明的要点是你读字节
你积累它们
试着看看你目前得到的东西是否是一个完整的请求
如果是-分析一下,剩下的留下次用
这假设请求相当小,并且不必流式传输,这是一个更高级的主题。在