在Python / Java服务器/客户端之间发送对象

时间:2019-06-15 11:52:03

标签: java python sockets object

我有一个 Python客户端和一个 Java服务器。我希望客户端发送对象到服务器。如何实现呢?

如何还实现其他方式( Java客户端-Python服务器)?

这是我使用Python服务器和Java客户端进行的尝试:

PYTHON服务器端

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

它所引用的对象(类SimpleMessage)的定义如下:

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

还有类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;
    }
}

输出

这是我在 Python服务器端上获得的输出:

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

这是我在 Java客户端上获得的输出:

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)

2 个答案:

答案 0 :(得分:1)

这是选择序列化格式的特定实例。

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

这是一个可能过于宽泛的主题,因此考虑到所有可能的格式,我将在冗长且可能多余的答案中予以保留。

JSON是一种很好的当前流行的格式,可以帮助您入门,但是将来在涉及更多的用例中也可能会很好地工作。在Python和Java中有著名的库。

无论您选择什么,如果在小型原型或任务之外还有任何用途,则定义显式架构将为将来的工作奠定良好基础(例如,将JSON架构用于JSON)。

与原始示例代码一样,

8是Python特定的序列化格式。因此,除非您在Java世界中对诸如Jython之类的工具有特定用途,否则在网络上与可以用另一种语言编写的服务进行通信不是一个好选择。

您还应考虑使用低级套接字是您使用情况的最佳选择,还是使用HTTP之类的高级网络库可能更合适。

答案 1 :(得分:1)

您在这里所说的也称为系统中元素的去耦。

这为您提供了很大的灵活性来更改系统中的语言和实现,这也是在微服务体系结构中不同的后端服务相互交谈时使用的方法。

执行此操作的常用方法是选择双方相互传输的JSON协议:例如:

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

然后在两个元素之间进行HTTP调用以获取GET或POST数据。

这样做,您可以自由地在每一侧更改实现(假设您发现最好用JavaScript编写客户端,并用R编写服务器)。

只要双方继续使用相同的协议,它们就与另一方使用的实现方式无关。