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

在Python/Java服务器/客户端之间发送对象,java,python,sockets,object,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.sets

我有一个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))
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
)定义如下:

#!/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客户端

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

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

这是一个可能有点过火的话题,所以考虑到所有可能的格式,我不会给出一个冗长且可能多余的答案

JSON是一种很好的、目前流行的格式,它可以让您开始使用,但也可能在将来更复杂的用例中很好地工作。Python和Java中都有著名的库

不管你选择什么,如果在一个小的原型或赋值之外有任何用途,定义一个明确的模式为将来的工作奠定了良好的基础(例如,使用JSON模式为JSON)。

pickle
,与原始示例代码一样,是一种特定于Python的序列化格式。因此,除非您在Java世界中对Jython这样的工具有特定的用途,否则它不是通过网络与可以用另一种语言编写的服务进行通信的好选择


您还应该考虑低级套接字是否是您的用例的最佳选择,或者像HTTP这样的更高级的网络库可能更适合。

这里所讨论的也被称为系统中元素的解耦。

这使您能够灵活地更改系统中的语言和实现,这也是在微服务体系结构中不同后端服务相互通信时使用的方法

通常的方法是选择双方相互传输的JSON协议:例如:

{
 fName: "David",
 lName: "Gold"
}
然后进行HTTP调用以获取或发布两个元素之间的数据

通过这样做,您可以自由地更改每一方的实现(假设您发现最好用JavaScript编写客户机,用R编写服务器)


只要双方继续使用相同的协议,他们就不知道对方使用的实现。

谢谢您的回答。你能给我举个具体的例子吗?我是否应该在这两个类中都创建一个方法…?@Robb1如果你觉得我的答案有帮助,我将感谢你投票支持它:-)它是:)如果你给我一些关于如何在我的例子中使用JSON的代码,我当然也会将它标记为正确的!;)谢谢你的回答。对于像我这样的小型应用程序,您认为什么是更好的选择?这只是一个练习,我希望看到它工作:)(一些代码也非常感谢):)