1

我有一个使用 Python Imaging Library 绘制图像的服务器端函数。Java 客户端请求一个图像,该图像通过套接字返回并转换为 BufferedImage。

我在数据前面加上要发送的图像大小,然后是 CR。然后我从套接字输入流中读取这个字节数,并尝试使用 ImageIO 转换为 BufferedImage。

在客户端的缩写代码中:

public String writeAndReadSocket(String request) {
    // Write text to the socket
    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    bufferedWriter.write(request);
    bufferedWriter.flush();

    // Read text from the socket
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    // Read the prefixed size
    int size = Integer.parseInt(bufferedReader.readLine());

    // Get that many bytes from the stream
    char[] buf = new char[size];
    bufferedReader.read(buf, 0, size);
    return new String(buf);
}

public BufferedImage stringToBufferedImage(String imageBytes) {
    return ImageIO.read(new ByteArrayInputStream(s.getBytes()));
}

和服务器:

# Twisted server code here

# The analog of the following method is called with the proper client
# request and the result is written to the socket.
def worker_thread():
    img = draw_function()
    buf = StringIO.StringIO()
    img.save(buf, format="PNG")
    img_string = buf.getvalue()
    return "%i\r%s" % (sys.getsizeof(img_string), img_string)

这适用于发送和接收字符串,但图像转换(通常)失败。我试图理解为什么图像没有被正确读取。我最好的猜测是客户端没有读取正确的字节数,但老实说我不知道​​为什么会这样。

旁注:

  • 我意识到 char[]-to-String-to-bytes-to-BufferedImage Java 逻辑是迂回的,但是直接读取字节流会产生相同的错误。
  • 我有一个版本,其中客户端套接字不是持久的,即。处理请求并断开连接。该版本工作正常,因为我不需要关心图像大小,但我想了解为什么建议的方法不起作用。
4

3 回答 3

2
  1. BufferedReader.read()不能保证填充缓冲区,并且将图像转换为字符串并返回不仅没有意义而且是错误的。

  2. 字符串不是二进制数据的容器,并且不能保证往返工作。

最好重新设计协议,这样您就可以摆脱readLine(),并以二进制形式发送长度,并且可以使用DataInputStream.

一般来说,在处理二进制协议时,答案总是DataInputStreamand DataOutputStream,除非字节顺序不是规范的网络字节顺序,这是一个协议设计错误,在这种情况下你需要查看 byte-ordered ByteBuffers

于 2012-06-12T22:16:29.130 回答
1

在服务器代码中,您的使用sys.getsizeof是错误的。这将返回字节串对象的大小,而您想要的是字节串中的字节数,即它的长度len(img_string)

此外,在客户端代码中,该.readLine方法读取字符,直到它看到'\r'可能跟随'\n''\n',因此'\r'如果图像数据的第一个字节恰好是 0x0A,即 0x0A,则用作终止符将导致问题'\n'

于 2012-06-12T22:20:01.980 回答
0

我预计问题在于您正在尝试使用 aReadergetBytes()读取二进制数据(图像)。

Reader堆栈将从底层套接字流中获取字节,将它们转换为字符(使用平台的默认字符编码),并将它们作为字符串返回。然后再次使用默认编码将字符串内容转换回字节。对于二进制数据,字节到字符的初始转换可能是“有损”的。

解决方法是不使用Reader/ BufferedReader。使用一个InputStream和一个BufferedInputStream。通过发送编码为文本的图像大小并不能让自己变得容易,但是您可以通过一次读取一个字节直到获得换行符并将它们“手动”转换为整数来处理它。

(如果大小以“网络顺序”作为固定大小的二进制整数发送,您可以DataInputStream改用...)

于 2012-06-12T22:29:58.590 回答