提问人:XLC 提问时间:11/17/2023 最后编辑:XLC 更新时间:11/17/2023 访问量:43
Python 中的套接字与 Ubuntu
Socket in Python with Ubuntu
问:
我正在使用 Python Socket 来实现 Ubuntu Server 中两个本地进程之间的交互。发生了一些奇怪的事情。当我在 Mac (i7) 中本地运行这两个进程时,它们在 1 秒内快速运行。但是,当我在 Ubuntu Server 中运行它们时,它的成本超过 30 秒。
我认为 TCP 在 Send() 和 Recv() 之间被阻塞了。当我只是让服务器发送和客户端接收消息时。然后,这些进程也可以在 1 秒内运行。所以我想知道发生了什么,是否有可能修复它。非常感谢!
这是代码
服务器:
if __name__=='__main__':
server1 = ServerSocket("127.0.0.1", 4321)
server1._conn_client()
print("xxx");
start_time = time.time()
for i in range(10000):
server1.Recv()
server1.Send("hello") ## delete this row to disable the server to send messages
print(i)
end_time = time.time()
print("Server time:", end_time - start_time)
server1.Send("hello")
msg = server1.Recv()
print("hi:", msg)
server1.close()
客户:
if __name__ == '__main__':
client = ClientSocket("127.0.0.1", 4321)
client.Connect()
print("xxx");
start = time.time()
for i in range(10000):
client.Send("hello from client1")
client.Recv() ## delete this to disable the cleint to receive messages
end = time.time()
print("Client time:", end - start)
msg =client.Recv()
print(msg)
client.Send("hello from client1")
client.close()
从其他套接字定义的函数:
class ServerSocket(object):
def __init__(self, ip="127.0.0.1", port=7778):
self.ip = ip
self.port = port
self._buffer_size = 80000
self._init_socket()
self._socket.settimeout(3000)
def _init_socket(self):
self._socket = socket.socket()
ip_port = (self.ip, self.port)
self._socket.bind(ip_port)
def _conn_client(self):
self._socket.listen(100)
self._client_socket, addr = self._socket.accept()
self._client_socket.settimeout(3000)
def Recv(self):
msg_len_pack = self._client_socket.recv(4)
# print(struct.unpack('i', msg_len_pack))
msg_len = struct.unpack('i', msg_len_pack)[0]
# print("msg_len:", msg_len, "buffer:", self._buffer_size)
if msg_len < self._buffer_size:
msg_pack = self._client_socket.recv(msg_len)
msg = json.loads(msg_pack.decode('utf-8'))
return msg
def Send(self,data):
msg_pack = json.dumps(data).encode('utf-8')
msg_len_pack = struct.pack('i', len(msg_pack))
self._client_socket.send(msg_len_pack)
self._client_socket.send(msg_pack)
def close(self):
self._client_socket.close()
class ClientSocket(object):
def __init__(self, ip="127.0.0.1", port=7778):
self.ip = ip
self.port = port
self._buffer_size = 80000
def Connect(self):
self._socket = socket.socket()
self._socket.connect((self.ip,self.port))
def Send(self, data):
msg_pack = json.dumps(data).encode('utf-8')
msg_len_pack = struct.pack('i', len(msg_pack))
self._socket.send(msg_len_pack)
self._socket.send(msg_pack)
def Recv(self):
msg_len_pack = self._socket.recv(4)
msg_len = struct.unpack('i', msg_len_pack)[0]
if msg_len < self._buffer_size:
msg_pack = self._socket.recv(msg_len)
msg = json.loads(msg_pack.decode('utf-8'))
return msg
def close(self):
self._socket.close()
答:
-1赞
Tricotou
11/17/2023
#1
巨大的延迟来自您的优化:D 啊哈,开个玩笑,我理解你使用 struct 发送超过 4 个字节的 msg 大小的意愿,然后发送完整的 msg,而接收者等待确切的 msg 长度,等等......但在你的情况下,这是一个“错误”的优化。只需坚持默认缓冲区大小,如 1024 或 4096 或任何 2 的幂,不要太大,也不要太小。
然后处理它:你仍然可以发送JSON数据来提供有关未来的信息,关于下一个“大消息”的信息,这将是4 GB或其他什么,它将通过多个套接字数据包发送,仅此而已
另外,让我们避免在相同时将代码加倍,在您的情况下,可以完成单个类:
class Socket(object):
def __init__(self, ip="127.0.0.1", port=7778, buffer=1024, is_server=False):
self.buffer = buffer
if is_server:
self._socket = socket.socket()
self._socket.bind((ip, port))
self._socket.listen()
self._connected_socket, addr = self._socket.accept()
else:
self._connected_socket = socket.socket()
self._connected_socket.connect((ip, port))
def Recv(self):
msg_pack = self._connected_socket.recv(self.buffer)
msg = json.loads(msg_pack.decode('utf-8'))
return msg
def Send(self, data):
msg_pack = json.dumps(data).encode('utf-8')
self._connected_socket.send(msg_pack)
def close(self):
self._connected_socket.close()
然后你只需为客户端实例化一种不同的方式:
if __name__ == '__main__':
client = Socket(port=4321)
print("xxx");
start = time.time()
for i in range(10000):
client.Send("hello from client1")
client.Recv()
end = time.time()
print("Client time:", end - start)
msg = client.Recv()
print(msg)
client.Send("hello from client1")
client.close()
对于服务器:
if __name__=='__main__':
server1 = Socket(port=4321, is_server=True)
print("xxx");
start_time = time.time()
for i in range(10000):
server1.Recv()
server1.Send("hello")
print(i)
end_time = time.time()
print("Server time:", end_time - start_time)
server1.Send("hello")
msg = server1.Recv()
print("hi:", msg)
server1.close()
在 Ubuntu 上,超过 10 000 次的循环总共不到 0.3 秒,包括我猜大部分时间的打印......
评论
0赞
XLC
11/24/2023
你好!很抱歉,由于工作繁忙,回复晚了。我尝试了您的代码,它有效!多谢!这是非常有帮助的!
评论
ClientSocket
ServerSocket
send_message(socket, message)
receive_message(socket)
_buffer_size