1

I've read a few posts on how to send a picture using sockets in Python, and how to send a picture using sockets in Java, I was wanting to combine the two and send a picture from Python to Java using sockets on both ends. Most of my code is taken from the posts I read but here is the python client:

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()

the code for the Java server is:

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();
        }
    }
}

The initial problem comes from sending the size I think. I'm no python expert, nor am I a Java expert, but I think what's happening is Python is sending the size as a string and Java is receiving it as a byte array and converting it to an integer, and there are some differences in the way they are stored in the two languages. Can anyone offer any assistance with this issue?

2 Answers 2

2

Although I would approach your problem slightly differently, the following code works:

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(); }
    }
}

The sender opens a socket, reads the file, and sends the receiver the length. The receiver gets the length, parses the bytes and sends it back. Upon receipt of the "confirmation", the sender then sends the file contents. The receiver will then repeatedly read 1024 byte chunks from the socket input stream, inserting the bytes into img_data. When there are no more bytes expected (or the socket is closed), the receiver will send "OK" to the sender (unconditionally) and exit. The sender will just print that "OK" (in bytes), and exit.

Some of this could be cleaned up with a ByteArrayOutputStream, but I wanted to get as close to the functionality of your code as possible.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, your solution worked fine for me. Now might you be able to tell my why my solution didn't work?
1

Something is off - you should be getting some kind of error when trying to send some integer in the socket:

>>> 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'

Sockets can only send bytes, you have to convert the int object containing the size to bytes somehow, python won't do it automatically for you. Your code should fail with the error above.

In the java code you are using asIntBuffer() and Integer.toBinaryString to convert your values, in the python code you just try to send the data without converting, you should get error.

Now, to convert the int to bytes, you can use the struct module; It will convert to a binary representation used by the C language - I think that's what your java code expect

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

In the same way, you should use struct.unpack to convert the bytes back to a integer object. See the documentation for more details and a table of possible conversions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.