Reputation: 5025
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
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
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