Robb1
Robb1

Reputation: 5025

Sending objects between Python/Java server/client

I have a Python client and a Java server. I would like the client to send an object to the server. How to implement this?

How to also implement the other way around (Java client - Python server)?

Here's an attempt I made with Python server and Java client:

PYTHON SERVER SIDE

import pickle
import socket

from simple_message import SimpleMessage

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 9999))
s.listen(1)

while True:
    print("Waiting for a message...")
    conn, addr = s.accept()
    data = conn.recv(4096)
    incoming_message = pickle.loads(data)
    conn.close()  # Close connection, not needed anymore
    print(SimpleMessage.get_payload(incoming_message))

The object it refers to (of class SimpleMessage) is defined as follows:

#!/usr/bin/env python


class SimpleMessage:
    dest_address = str()
    message_type = int()
    payload = str()

    def __init__(self, dest_address, message_type, payload):
        self.dest_address = dest_address
        self.message_type = message_type
        self.payload = payload

    def get_payload(self):
        return self.payload

JAVA CLIENT SIDE

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

public class JavaClient {
    public static void main(String[] args) throws IOException {
        Socket sendingSocket = new Socket();
        sendingSocket.connect(new InetSocketAddress("127.0.0.1", 9999));
        OutputStream outputStream = sendingSocket.getOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        SimpleMessage message = new SimpleMessage("127.0.0.1", 1, "Test message!");
        objectOutputStream.writeObject(message); // Write Message on socket
        sendingSocket.close();
    }
}

And the class SimpleMessage:

import java.io.Serializable;

public class SimpleMessage implements Serializable {
    private String destAddress;
    private Integer messageType;
    private String payload;

    public SimpleMessage(String destAddress, Integer messageType, String payload) {
        this.destAddress = destAddress;
        this.messageType = messageType;
        this.payload = payload;
    }
}

OUTPUTS

Here is the output I get on the Python server side:

Waiting for a message...
Traceback (most recent call last):
  File "python_server.py", line 16, in <module>
    incoming_message = pickle.loads(data)
_pickle.UnpicklingError: invalid load key, '\xac'.

And here's the output I get on the Java client side:

Exception in thread "main" java.net.SocketException: Broken pipe (Write failed)
    at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
    at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
    at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1883)
    at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1792)
    at java.base/java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1287)
    at java.base/java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1232)
    at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1428)
    at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
    at java.base/java.io.ObjectOutputStream.writeFatalException(ObjectOutputStream.java:1583)
    at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:352)

Upvotes: 2

Views: 1034

Answers (2)

riorio
riorio

Reputation: 6816

What you are talking about here is also known as decoupling of elements in the systems.

This gives you a lot of flexibility to change languages and implementation in the system and this is also the method that is used when different backend services talk with each other in a micro-services architecture.

The common way to do it is to select a JSON protocol that the two sides transfer between each other: For example:

{
 fName: "David",
 lName: "Gold"
}

And then to make HTTP calls to GET or POST data between your two elements.

By doing so, you are free to change the implementation on each side (let's say you discover that you better write your client in JavaScript and the server in R).

As long as both sides keep working with the same protocol, they are agnostic to the implementation that the other side uses.

Upvotes: 1

Adam Burke
Adam Burke

Reputation: 864

This is a specific instance of choosing a serialization format.

https://en.wikipedia.org/wiki/Comparison_of_data-serialization_formats

This is a potentially overbroad topic, so I will hold back from a long and possibly redundant answer considering all possible formats.

JSON is a good and currently fashionable format which will get you started, but also potentially work well more involved use cases in the future. There are well-known libraries in Python and Java.

No matter what you choose, if there is any use outside a small prototype or assignment, defining an explicit schema lays a good foundation for future work (eg using JSON schema for JSON).

pickle, as in your original example code, is a Python-specific serialization format. So unless you have some specific use for a tool like Jython in your Java world, it's not a great choice for communicating over a network with a service that can be written in another language.

You should also consider whether low level sockets are the best choice for your use case, or a higher level network library like HTTP may be a better fit.

Upvotes: 1

Related Questions