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

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (265)

我希望将java和python结合起来,并使用两端的套接字将图片从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将其作为字节数组接收并转换为整数,它们在两种语言中的存储方式有一些不同。有人能在这个问题上提供任何帮助吗?

提问于
用户回答回答于

有些东西是错的-当试图在套接字中发送整数时,你应该得到某种错误:

>>> 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代码中,你只需尝试发送数据而不进行转换,就会得到错误。

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

 size_in_bytes = struct.pack('I', len(data_to_send))
用户回答回答于

虽然我会稍微不同地处理你的问题,但是下面的代码可以工作:

Python Sender:

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 Receiver:

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,但我希望尽可能接近代码的功能。

扫码关注云+社区

领取腾讯云代金券