当前位置: 首页 > 知识库问答 >
问题:

在Java客户端和Twisted Python套接字服务器之间发送缓冲图像

温亮
2023-03-14

我有一个服务器端函数,它使用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-BufferedImageJava逻辑是迂回的,但是直接读取字节流会产生相同的错误。
  • 我有一个客户端套接字不持久的版本,即。处理请求并删除连接。该版本运行良好,因为我不需要关心图像大小,但我想了解为什么提出的方法不起作用。

共有3个答案

施洛城
2023-03-14

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

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

修复方法是不使用BufferedReader读取器。使用输入流和缓冲输入流。通过发送编码为文本的图像大小并不能让您自己变得容易,但您可以通过每次读取一个字节,直到得到换行符,然后“手动”将其转换为整数来处理。

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

严恩
2023-03-14

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

此外,在客户机代码中,。readLine方法读取字符,直到它看到可能跟在后面的是“\r”或”\n“,因此如果图像数据的第一个字节恰好是0x0A,即“\r”,则使用作为终止符将导致问题。

韦宏扬
2023-03-14

>

String不是二进制数据的容器,也不能保证往返运行。

最好重新设计协议,这样就可以去掉readLine(),以二进制形式发送长度,并可以使用DataInputStream读取整个流。

一般来说,在处理二进制协议时,答案总是数据输入流(DataInputStream)和数据输出流(DataOutputStream),除非字节顺序不是规范的网络字节顺序,这是一个协议设计错误,在这种情况下,您需要查看字节顺序的字节缓冲区(ByteBuffers)。

 类似资料:
  • 我正试图从套接字服务器(Java)向套接字客户端(Python)发送一个映像,但客户端中接收到的映像大小不正确,无法打开。我不知道我做错了什么。有什么建议吗?

  • 我有一个java服务器应用程序,可以通过与多个客户端通信。在这个通道上,客户端发送请求,服务器发送应答。现在我想添加一个功能,服务器可以将文件发送到客户端。我不想通过用于通信的套接字发送,所以在一个客户端和一个服务器之间使用更多套接字是个好主意吗?如果是,如何处理?我用过这样的东西吗? 还是有更好的办法?

  • 我有以下情况, TCP服务器将接受来自客户端的连接 客户端将发送第一个请求,服务器将响应该请求,服务器必须在同一套接字上等待接收来自同一客户端的下一个请求 请参阅我所做的代码,使用此代码,服务器无法接收服务器发送的第二个请求,而客户端也在第二个接收中接收来自服务器的第一个响应。 请对此提出建议,代码中的问题是什么。 我试着模拟这个案例,如果有人以前遇到过,请尽快建议。

  • 问题内容: 我有一个C ++服务器和两个客户端(红宝石和Java)。一切都在64位linux机器(java 1.7.0_17)上运行。ruby客户端可以正常工作,但是java版本会出现问题。 在Java中,我尝试将字符串从客户端发送到服务器。实际上,服务器收到了整个字符串,但是服务器认为还有更多东西要接收。 红宝石客户端看起来像这样: 这里的一切工作正常。红宝石客户端发送一个字符串。服务器接收该字

  • 我试图用java实现一个客户端服务器,在这里我读取客户端中的输入并在服务器中执行UperCase,然后返回客户端并打印UperCase。我使用ObjectOutputStream和ObjectInputStream进行读写,但是当我在客户机中键入一个msg时,程序会显示以下错误: Digite uma msg casa java.io.eofexception位于java.io.datainput

  • 我有一个关于Java插座的技术问题。 例如,假设我有一个Java Sockets服务器和n个多个客户端。是否可以几乎实时地将数据从服务器发送到任何或所有客户端? 更准确地说: 有哪种监听器可以在Sockets客户端中实现 有人能告诉我什么方法是最好的吗?此外,如果有人有一个代码示例,我也会很高兴。 谢谢