我的Java-Python套接字有问题。我的目标是通过套接字tcp将Java应用程序中的Json对象发送到python脚本并接收响应,但是Json发送后套接字被阻塞。下面是我的代码:

try {
    Socket socket = new Socket(dstAddress, dstPort);
    is = new DataInputStream(socket.getInputStream());
    os = new DataOutputStream(socket.getOutputStream());
    PrintWriter pw = new PrintWriter(os, true);
    pw.println(jsonObject.toString());
    System.out.println("Send to the socket jsonObject.");

    BufferedReader in = new BufferedReader(new InputStreamReader(is));
    String response = in.readLine();
    System.out.println("Response: " + response);
    is.close();
    os.close();


} catch (IOException e) {
    e.printStackTrace();
} catch (InterruptedException e) {
    e.printStackTrace();
}

在以下几行python代码中:
HOST = "192.168.1.101" #localhost
PORT = 7011
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

while (1):
    print("\n\nAttending for client.....\n\n")
    conn, addr = s.accept()
    print("Connected by: " , addr)

    data = ""
    while 1:
        temp = conn.recv(1024).decode()
        if not temp:
            break
        data = data + temp

    print("JSON Received!!!!!")

    imageJson = {}
    imageJson = json.loads(data)

    # responding to the client
    response = DbImages[elem[0]]

    resp = "Prova"
    conn.send(resp.encode())

如果我终止Java代码(ctrl + C),则从block和json退出的套接字将到达python。问题是什么?问题似乎出在in.readLine()。如果我删除该语句,那么套接字可以正常工作。

最佳答案

您的Python代码正在等待Java端完成操作并发送EOF,然后再进行响应(这就是recv的含义,直到您得到一个空字节)。

您的Java代码正在等待Python端响应,然后再关闭套接字。

因此,他们都在互相等待。

删除readLine意味着Java代码不再等待任何内容,因此发送完成后它就立即卡在Python代码上,这确实使问题消失了,但实际上,这并不是很多解决方案需要回应。

那么,他们应该怎么做?好吧,有几种不同的选择。

  • 使用成帧协议(protocol),其中Java端要么在每条消息之后发送“消息完成”定界符,要么在每条消息之前发送 header (例如消息的字节长度)。因此,Python代码可以读取直到收到完整的消息为止,而不是直到EOF为止。
  • 如果您以紧凑格式对JSON进行编码,除了可打印的ASCII转义符外,其他所有内容都可以转义,则分隔符可以只是换行符(此时,您使用JSONlines作为协议(protocol)),Python代码可以在套接字上使用makefile并调用readline而不是循环到recv
  • 作弊并使用JSON,就好像它是框架协议(protocol)一样。并非如此,但是只要您发送的唯一顶级值是对象和数组,它就可以工作。然后,每次接收后,Python代码都可以使用raw_decode(请参阅json模块文档),直到成功为止。
  • 如果您只打算发送一条消息,则只需从Java关闭套接字(关闭写端),然后Python将获得其EOF并在套接字仍打开的另一端进行响应。 (这听起来似乎很hacky,但这实际上是很普遍的,尽管HTTP 1.1使事情变得有些复杂,但是它实际上是网络浏览器的工作方式。)
  • 10-04 23:07
    查看更多