如何使用套接字将字节从Python发送到Java?

时间:2018-06-29 23:28:21

标签: java python image sockets networking

我已经阅读了几篇关于如何使用Python中的套接字发送图片以及如何使用Java中的套接字发送图片的文章,我想将两者结合起来,并使用on上的套接字将图片从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以字节数组形式接收大小并将其转换为整数,并且在它们以两种语言存储的方式。有人可以提供有关此问题的任何帮助吗?

2 个答案:

答案 0 :(得分:1)

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

>>> 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不会自动为您完成。您的代码应因上述错误而失败。

在Java代码中,您正在使用asIntBuffer()Integer.toBinaryString来转换值,在python代码中,您只是尝试发送数据而不进行转换,则应该会出错。

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

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

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

答案 1 :(得分:0)

尽管我对您的问题的处理方式略有不同,但以下代码有效:

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”(以字节为单位),然后退出。

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