Python中的Socket与Ubuntu

bogh5gae  于 12个月前  发布在  Python
关注(0)|答案(1)|浏览(204)

我使用Python Socket在Ubuntu服务器上实现两个本地进程之间的交互。发生了一些奇怪的事情。当我在Mac(i7)上本地运行两个进程时,它们在1秒内快速运行。但是,当我在Ubuntu服务器上运行它们时,花费超过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()

qvtsj1bj

qvtsj1bj1#

巨大的延迟来自于你的优化:D啊哈,开玩笑的,我理解你使用结构体发送超过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上,超过10000的循环总共不到0.3秒,包括打印,我猜这需要大部分时间。

相关问题