Python中的Socket与Ubuntu

bogh5gae  于 2024-01-06  发布在  Python
关注(0)|答案(1)|浏览(294)

我使用Python Socket在Ubuntu服务器上实现两个本地进程之间的交互。发生了一些奇怪的事情。当我在Mac(i7)上本地运行两个进程时,它们在1秒内快速运行。但是,当我在Ubuntu服务器上运行它们时,花费超过30秒。
我认为TCP在Send()和Recv()之间被阻塞。当我只是让服务器发送和客户端接收消息时。然后进程也可以在1秒内运行。所以我想知道发生了什么,是否有可能修复它。非常感谢!
这里是代码
伺服器:

  1. if __name__=='__main__':
  2. server1 = ServerSocket("127.0.0.1", 4321)
  3. server1._conn_client()
  4. print("xxx");
  5. start_time = time.time()
  6. for i in range(10000):
  7. server1.Recv()
  8. server1.Send("hello") ## delete this row to disable the server to send messages
  9. print(i)
  10. end_time = time.time()
  11. print("Server time:", end_time - start_time)
  12. server1.Send("hello")
  13. msg = server1.Recv()
  14. print("hi:", msg)
  15. server1.close()

字符串
委托方:

  1. if __name__ == '__main__':
  2. client = ClientSocket("127.0.0.1", 4321)
  3. client.Connect()
  4. print("xxx");
  5. start = time.time()
  6. for i in range(10000):
  7. client.Send("hello from client1")
  8. client.Recv() ## delete this to disable the cleint to receive messages
  9. end = time.time()
  10. print("Client time:", end - start)
  11. msg =client.Recv()
  12. print(msg)
  13. client.Send("hello from client1")
  14. client.close()


从其他函数定义的套接字函数:

  1. class ServerSocket(object):
  2. def __init__(self, ip="127.0.0.1", port=7778):
  3. self.ip = ip
  4. self.port = port
  5. self._buffer_size = 80000
  6. self._init_socket()
  7. self._socket.settimeout(3000)
  8. def _init_socket(self):
  9. self._socket = socket.socket()
  10. ip_port = (self.ip, self.port)
  11. self._socket.bind(ip_port)
  12. def _conn_client(self):
  13. self._socket.listen(100)
  14. self._client_socket, addr = self._socket.accept()
  15. self._client_socket.settimeout(3000)
  16. def Recv(self):
  17. msg_len_pack = self._client_socket.recv(4)
  18. # print(struct.unpack('i', msg_len_pack))
  19. msg_len = struct.unpack('i', msg_len_pack)[0]
  20. # print("msg_len:", msg_len, "buffer:", self._buffer_size)
  21. if msg_len < self._buffer_size:
  22. msg_pack = self._client_socket.recv(msg_len)
  23. msg = json.loads(msg_pack.decode('utf-8'))
  24. return msg
  25. def Send(self,data):
  26. msg_pack = json.dumps(data).encode('utf-8')
  27. msg_len_pack = struct.pack('i', len(msg_pack))
  28. self._client_socket.send(msg_len_pack)
  29. self._client_socket.send(msg_pack)
  30. def close(self):
  31. self._client_socket.close()
  32. class ClientSocket(object):
  33. def __init__(self, ip="127.0.0.1", port=7778):
  34. self.ip = ip
  35. self.port = port
  36. self._buffer_size = 80000
  37. def Connect(self):
  38. self._socket = socket.socket()
  39. self._socket.connect((self.ip,self.port))
  40. def Send(self, data):
  41. msg_pack = json.dumps(data).encode('utf-8')
  42. msg_len_pack = struct.pack('i', len(msg_pack))
  43. self._socket.send(msg_len_pack)
  44. self._socket.send(msg_pack)
  45. def Recv(self):
  46. msg_len_pack = self._socket.recv(4)
  47. msg_len = struct.unpack('i', msg_len_pack)[0]
  48. if msg_len < self._buffer_size:
  49. msg_pack = self._socket.recv(msg_len)
  50. msg = json.loads(msg_pack.decode('utf-8'))
  51. return msg
  52. def close(self):
  53. self._socket.close()

qvtsj1bj

qvtsj1bj1#

巨大的延迟来自于你的优化:D啊哈,开玩笑的,我理解你使用结构体发送超过4字节的msg大小,然后稍后发送完整的msg,而接收方等待确切的msg长度,等等.但这是一个“错误”的优化在你的情况下。只要坚持默认的缓冲区大小,如1024或4096或任何2的幂,不太大也不太小。
然后处理它:你仍然可以发送JSON数据来给予关于未来的信息,关于下一个“大消息”,这将是4 GB或什么,它将通过多个套接字包发送,仅此而已
此外,让我们避免在相同的情况下重复代码,在您的情况下,可以使用单个类:

  1. class Socket(object):
  2. def __init__(self, ip="127.0.0.1", port=7778, buffer=1024, is_server=False):
  3. self.buffer = buffer
  4. if is_server:
  5. self._socket = socket.socket()
  6. self._socket.bind((ip, port))
  7. self._socket.listen()
  8. self._connected_socket, addr = self._socket.accept()
  9. else:
  10. self._connected_socket = socket.socket()
  11. self._connected_socket.connect((ip, port))
  12. def Recv(self):
  13. msg_pack = self._connected_socket.recv(self.buffer)
  14. msg = json.loads(msg_pack.decode('utf-8'))
  15. return msg
  16. def Send(self, data):
  17. msg_pack = json.dumps(data).encode('utf-8')
  18. self._connected_socket.send(msg_pack)
  19. def close(self):
  20. self._connected_socket.close()

字符串
然后你只需要为客户端示例化一种不同的方式:

  1. if __name__ == '__main__':
  2. client = Socket(port=4321)
  3. print("xxx");
  4. start = time.time()
  5. for i in range(10000):
  6. client.Send("hello from client1")
  7. client.Recv()
  8. end = time.time()
  9. print("Client time:", end - start)
  10. msg = client.Recv()
  11. print(msg)
  12. client.Send("hello from client1")
  13. client.close()


对于服务器:

  1. if __name__=='__main__':
  2. server1 = Socket(port=4321, is_server=True)
  3. print("xxx");
  4. start_time = time.time()
  5. for i in range(10000):
  6. server1.Recv()
  7. server1.Send("hello")
  8. print(i)
  9. end_time = time.time()
  10. print("Server time:", end_time - start_time)
  11. server1.Send("hello")
  12. msg = server1.Recv()
  13. print("hi:", msg)
  14. server1.close()


在Ubuntu上,超过10000的循环总共不到0.3秒,包括打印,我猜这需要大部分时间。

展开查看全部

相关问题