Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python TCP套接字recv(1)与recv(n)的效率_Python_Sockets_Tcp - Fatal编程技术网

Python TCP套接字recv(1)与recv(n)的效率

Python TCP套接字recv(1)与recv(n)的效率,python,sockets,tcp,Python,Sockets,Tcp,我正在构建一个TCP应用程序,它使用换行符\n来分隔长度未知(但通常

我正在构建一个TCP应用程序,它使用换行符
\n
来分隔长度未知(但通常<64字节)的消息。我发现它非常有用

recv
的最佳(即最有效/最快)方法是一次一个字符,并检查它是换行还是
recv
更大的缓冲区并在类中存储“剩余”

一次一个

def __recv_until_newline(self):
    message = ""
    while True:
        chunk = self.socket.recv(1)
        if chunk == "" or chunk == "\n":
            break
        message += chunk
    return message
维护缓冲区

def __recv_until_newline(self):
    """ self.__buffer holds previously received message parts"""
    message = self.__buffer
    while True:
        chunk = self.socket.recv(64)
        message += chunk
        if chunk == "" or "\n" in message:
            break

    # something a bit more intelligent than this in reality, but you get the idea
    messages = message.split('\n')
    self.__buffer = "".join([x for x in message[1:]])
    return messages[0]

获得大数据块肯定更有效,因为您所做的操作更少。这样想:如果您有一条长度为1000的消息,那么在第一种情况下,您的循环将触发1000次,在第二种情况下仅触发16次。性能损失是显而易见的。当然,这是因为Python,但即使在操作系统级别,它也更高效,因为同样的原因:进行1000次sys调用instad Of 16。另外,扫描长度为64的字符串(顺便说一句:您应该扫描
chunk
而不是
message
)比64次调用
recv
更便宜。差不多就是这样。

获得大数据块肯定更有效,因为你做的操作更少。这样想:如果您有一条长度为1000的消息,那么在第一种情况下,您的循环将触发1000次,在第二种情况下仅触发16次。性能损失是显而易见的。当然,这是因为Python,但即使在操作系统级别,它也更高效,因为同样的原因:进行1000次sys调用instad Of 16。另外,扫描长度为64的字符串(顺便说一句:您应该扫描
chunk
而不是
message
)比64次调用
recv
更便宜。差不多了。

谢谢你的回复。。。有点道理,只是实现有点混乱:)谢谢你的回复。。。有点道理,只是实现有点混乱:)还要注意,您的第一个版本具有二次复杂性。每次执行
message+=chunk
操作时,都会创建一个新的字符串对象,这意味着复制整个
message
,并添加最后一个字节。如果消息长度为64字节,那么第一个循环将简单地创建一个长度为1的字符串,第二个循环必须复制前一个字符串并添加1个字符,然后必须复制两个字符并添加另一个字符,最后您的成本大约为
sum(range(64))=2016
,而不是使用
recv(64)仅
64
。使用
列表
''。加入
可以避免这种二次行为。还要注意的是,您的第一个版本具有二次复杂性。每次执行
message+=chunk
操作时,都会创建一个新的字符串对象,这意味着复制整个
message
,并添加最后一个字节。如果消息长度为64字节,那么第一个循环将简单地创建一个长度为1的字符串,第二个循环必须复制前一个字符串并添加1个字符,然后必须复制两个字符并添加另一个字符,最后您的成本大约为
sum(range(64))=2016
,而不是使用
recv(64)仅
64
。使用
列表
'.join
可以避免这种二次行为。