【问题标题】:How to send bytes from Python to Java using sockets?如何使用套接字将字节从 Python 发送到 Java?
【发布时间】:2018-06-30 08:30:19
【问题描述】:

我已经阅读了几篇关于如何在 Python 中使用套接字发送图片以及如何在 Java 中使用套接字发送图片的文章,我想将两者结合起来并使用套接字将图片从 Python 发送到 Java两端。我的大部分代码都取自我阅读的帖子,但这里是 python 客户端:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect(("192.168.0.12",4141))

try:

    file = open("subbed.jpg", 'rb')
    bytes = file.read()
    print "{0:b}".format(len(bytes))
    size = len(bytes)
    s.sendall(size)

    answer = s.recv(4096)
    print "Answer = %s" %answer 

    if answer == 'GOT SIZE':
        s.sendall(bytes)

        answer = s.recv(4096)

        if answer == 'GOT IMAGE' :
            s.sendall("byte")
    file.close()
finally:
    s.close()

Java 服务器的代码是:

public static void main(String[] args) {
    while(true) {
        try (
                ServerSocket server = new ServerSocket(PORT_NUMBER);
                Socket client = server.accept();
                PrintWriter out = new PrintWriter(client.getOutputStream(), true);
                InputStream in = client.getInputStream()) {
            System.out.println("GOT CONNECTION FROM: " + client.getInetAddress().toString());
            byte[] sizeAr = new byte[4];

            in.read(sizeAr);
            int size = ByteBuffer.wrap(sizeAr).asIntBuffer().get();
            System.out.println(Integer.toBinaryString(size));
            out.println("GOT SIZE");

            byte[] imageAr = new byte[size];
            in.read(imageAr);

            BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageAr));
            ImageIO.write(image, "jpg", new File("C:\\myprivatelocation\\test.jpg"));

        } catch (Exception ioe) {
            ioe.printStackTrace();
        }
    }
}

最初的问题来自于发送我认为的尺寸。我不是 python 专家,也不是 Java 专家,但我认为发生的事情是 Python 将大小作为字符串发送,而 Java 将其作为字节数组接收并将其转换为整数,并且存在一些差异它们以两种语言存储的方式。任何人都可以在这个问题上提供任何帮助吗?

【问题讨论】:

    标签: java python image sockets networking


    【解决方案1】:

    虽然我会稍微不同地处理您的问题,但以下代码有效:

    Python 发送器

    import socket
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect(("127.0.0.1", 8888))
    
        with open("C:\\temp\\test-input.jpg", 'rb') as f:
            content = f.read()
    
        size = len(content)
        print("File bytes:", size)
        s.sendall(size.to_bytes(4, byteorder='big'))
    
        buff = s.recv(4)
        resp = int.from_bytes(buff, byteorder='big')
        print("Response:", resp)
    
        if size == resp:
            s.sendall(content)
    
        buff = s.recv(2)
        print(buff)
    
    print("Complete.")
    

    Java 接收器

    import java.awt.image.BufferedImage;
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.ByteBuffer;
    
    
    import javax.imageio.ImageIO;
    
    class Server{
        public static void main(String[] args) {
            int PORT_NUMBER = 8888;
    
            try (
                ServerSocket server = new ServerSocket(PORT_NUMBER);
                Socket client = server.accept();
                OutputStream sout = client.getOutputStream();
                InputStream sin = client.getInputStream();
            ){
                System.out.println("GOT CONNECTION FROM: " + client.getInetAddress().toString());
    
                // Get length
                byte[] size_buff = new byte[4];
                sin.read(size_buff);
                int size = ByteBuffer.wrap(size_buff).asIntBuffer().get();
                System.out.format("Expecting %d bytes\n", size);
    
                // Send it back (?)
                sout.write(size_buff);
    
                // Create Buffers
                byte[] msg_buff = new byte[1024];
                byte[] img_buff = new byte[size];
                int img_offset = 0;
                while(true) {
                    int bytes_read = sin.read(msg_buff, 0, msg_buff.length);
                    if(bytes_read == -1) { break; }
    
                    // Copy bytes into img_buff
                    System.arraycopy(msg_buff, 0, img_buff, img_offset, bytes_read);
                    img_offset += bytes_read;
                    System.out.format("Read %d / %d bytes...\n", img_offset, size);
    
                    if(img_offset >= size) { break; }
                }
                BufferedImage image = ImageIO.read(new ByteArrayInputStream(img_buff));
                ImageIO.write(image, "jpg", new File("C:\\temp\\test-output.jpg"));
    
                // Send "OK"
                byte[] OK = new byte[] {0x4F, 0x4B};
                sout.write(OK);
            }
            catch (IOException ioe) { ioe.printStackTrace(); }
        }
    }
    

    发送方打开一个套接字,读取文件,然后向接收方发送长度。接收者获取长度,解析字节并将其发回。在收到“确认”后,发送方随后发送文件内容。然后接收器会从套接字输入流中重复读取 1024 字节的块,将这些字节插入到img_data 中。当预期没有更多字节(或套接字已关闭)时,接收方将(无条件)向发送方发送“OK”并退出。发送者只会打印那个“OK”(以字节为单位),然后退出。

    其中一些可以用ByteArrayOutputStream 清理,但我想尽可能接近您的代码的功能。

    【讨论】:

    • 谢谢,您的解决方案对我来说效果很好。现在您能否告诉我为什么我的解决方案不起作用?
    【解决方案2】:

    有什么问题 - 当你试图在套接字中发送一些整数时,你应该会遇到某种错误:

    >>> import socket
    >>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    >>> s.connect(('localhost', 7777))
    >>> s.sendall(len(b'some bytes'))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: a bytes-like object is required, not 'int'
    

    套接字只能发送bytes,你必须以某种方式将包含大小的int对象转换为bytes,python不会自动为你做。您的代码应该会因上述错误而失败。

    在使用asIntBuffer()Integer.toBinaryString 转换值的java 代码中,在python 代码中你只是尝试发送数据而不进行转换,你应该得到错误。

    现在,要将int 转换为bytes,您可以使用struct 模块;它将转换为 C 语言使用的二进制表示 - 我认为这就是您的 java 代码所期望的

     size_in_bytes = struct.pack('I', len(data_to_send))
    

    同样,您应该使用struct.unpack 将字节转换回整数对象。请参阅documentation 了解更多详细信息和可能的转换表。

    【讨论】:

      猜你喜欢
      • 2016-04-28
      • 2016-08-31
      • 2020-11-20
      • 2020-08-29
      • 1970-01-01
      • 2020-07-13
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多