繁体   English   中英

如何在Python中从套接字拆分接收到的数据?

[英]How to split received data from socket in Python?

我正在尝试用Python编写我的第一个客户端服务器应用程序。 我的客户端将不同的命令发送到服务器端。 例如,其中之一是用于在命令外壳中执行命令。 看起来像:

client.send("execute".encode("utf-8"))
client.send(command.encode("utf-8"))

在服务器端,我试图通过这种方式接收它:

data = client.recv(BUFF_SIZE).decode("utf-8").strip()
if data == "execute":
    command = client.recv(BUFF_SIZE).decode("utf-8").strip()
    ...

但是我在'data'变量中得到了“ execute {command}”字符串,并且==“ execute”条件没有得到满足。 我是客户机-服务器应用程序的新手,不知道如何正确执行它。 我做错了什么?

要实现的是TCP是字节流 从TCP获得的保证是,发送的字节将以相同的顺序到达。 如果字节流表示命令序列,则无法保证字节将以与您发送的内容对齐的块的形式到达。 您可能正在发送:“ execute”,“ command”,并接收“ e”,“ xecuteco”,“ mmand”。

(是的,这是极不可能的,而由于nagle算法,极有可能接收到“ executecommand”,但我离题了。关键是要编写健壮的代码,您无需承担任何其他责任,而只是TCP如何将数据分解成碎片)

因此,您需要决定的第一件事是如何将请求字节流划分为请求,以及如何将响应字节流划分为响应。 在请求内部,您需要确定其内部结构。

假设您确定请求看起来像:“ verb param1 param2 ... paramN \\ n”即:

  1. 请求是非换行字节的序列,后跟换行
  2. 该请求包含一个初始动词(非空格字符),后跟零个或多个参数

由于协议本身现在在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

当然,这必须由决定响应看起来如何以及如何将传入的字节流划定为响应序列的决定来补充。 我试图用这段代码说明的重点是

  1. 你读字节
  2. 你积累他们
  3. 尝试看看您到目前为止所获得的东西是否已被全部索取
  4. 如果是,请进行分析,然后将其余的留给下次

假设请求相当小,您不必流式传输,这是更高级的主题。

您可以通过将服务器代码上的if语句更改为以下内容来解决此问题:

if data.split("{")[0] == "execute"

说明:

data = "execute{command}"
print data.split("{")[0]

版画

"execute"

由于数据是字符串,因此可以使用split方法使用“ {”字符将字符串拆分为列表。

所以:

data.split("{")

会回来

["execute", "commmand}"]

并且由于您要“执行”,因此将列表中的索引设为0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM