4

我有一个简单的 python tcp 服务器(我正在使用SocketServer类)的问题,它必须从 java 客户端接收数据。

这里是服务器端代码:

class ServerRequestHandler(SocketServer.BaseRequestHandler):
    [...]
    def handle(self):
        requestCode = struct.unpack('>i', self.request.recv(4))[0]
        [...]
    [...]

这里有客户端:

addr = InetAddress.getByName(hostname);
SocketAddress sockaddr = new InetSocketAddress(addr, port);
clientSocket = new Socket();
clientSocket.connect(sockaddr, timeoutMs);
clientSocketDataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
int   requestCode = 1;
clientSocketDataOutputStream.writeInt(requestCode);
clientSocketDataOutputStream.flush();

我启动 Python 服务器,然后尝试执行必须向服务器发送整数的客户端。

在服务器端 Python 引发异常,因为该recv(4)函数不读取 4 个字节,它只返回一个字节。

事实上,我的 java 客户端正确发送了 4 个字节,如果我尝试调用recv(1)4 次,它会正确读取 4 个字节。

我尝试编写一个 Python 客户端来执行与我的 java 客户端相同的操作,在这种情况下,服务器recv(4)运行良好。

如何解决这个问题呢?我想实现一个简单的 pythonbuffered reader function来逐字节读取套接字,但我确信存在更智能的解决方案。

4

3 回答 3

5

recv 不必读取 4 个字节,它只抓取最多 4 个字节的任何内容。因为,正如您所说,您可以调用 recv(1) 4 次。你可以这样做

def recvall(sock, size):
    msg = ''
    while len(msg) < size:
        part = sock.recv(size-len(msg))
        if part == '': 
            break # the connection is closed
        msg += part
    return msg

这将重复调用recvsock直到size收到字节。如果part == ''套接字已关闭,则它将返回关闭前的任何内容

所以改变

requestCode = struct.unpack('>i', self.request.recv(4))[0]

requestCode = struct.unpack('>i', recvall(self.request, 4))[0]

我建议recvall为您的班级制作一种方法以使事情变得更清洁。


这是对此处定义的安全套接字类的方法的修改:http: //docs.python.org/howto/sockets.html

于 2012-08-08T19:35:27.470 回答
0

recv(4)最多读取4 个字节。请参阅文档:http ://docs.python.org/library/socket.html 。我认为在这里制作一个简单的缓冲阅读器功能是一个完全可以接受的解决方案。

于 2012-08-08T19:33:42.670 回答
0

也许你可以使用io模块中的东西?例如BufferedRWPair 。

于 2012-08-08T19:35:28.050 回答