首页 > 解决方案 > 使用套接字将消息从 Java 客户端发送到 Python 服务器,反之亦然

问题描述

我正在尝试使用 Python 服务器和 Java 客户端发送接收数据。首先,Java 将字符串中的 JSON 发送到 Python Server。收到字符串后,Python 服务器将向客户端发送一个 JSON。客户端从服务器接收到 JSON 后,再次向服务器发送 JSON 字符串。(客户端始终发送相同的消息)这是一个递归过程。

ISSUE:当我同时执行 Python 服务器和 Java 后,Python 服务器收到 Java 客户端发送的消息并返回 JSON。但是在客户端,服务器发送的消息没有收到。

服务器.py

import socket
import threading
import json
import numpy

HEADER_INITIAL = 25

PORT = 1234
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'

    def handle_client(self, conn, addr):
        print(f"[NEW CONNECTION] {addr} connected.")

        connected = True
        while connected:
            msg = conn.recv(HEADER_INITIAL).decode(FORMAT)
            if msg:
                print("[DATA] RECEIVED"+ str(msg))
       
                x = {
                      "Sentence": "This is a value"
                    }
                y = json.dumps(x)
                conn.send(y.encode(FORMAT))
                conn.send("\n".encode(FORMAT));
        conn.close()        

客户端.java

    try (Socket socket = new Socket(Address, Port)) {

            InputStream input = socket.getInputStream();
            InputStreamReader reader = new InputStreamReader(input);

            OutputStream output = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(output, true);


            int  character;
            StringBuilder data = new StringBuilder();

            while(true){
                Thread.sleep(4000);
                String strJson = "{'message':'Hello World'}";
                JSONObject jsonObj = new JSONObject(strJson);

                writer.println(jsonObj.toString());
                while((character = reader.read()) != -1) {
                    data.append((char) character);
                }
                System.out.println(data);

            }
        } catch (UnknownHostException ex) {
            System.out.println("Server not found: " + ex.getMessage());
        } catch (IOException ex) {
            System.out.println("I/O error: " + ex.getMessage());
     }

更新 这是调试输出。我首先启动了服务器,然后启动了客户端。最初,服务器接收{'message':'Hello World'}客户端发送的值,然后服务器将变量的值发送回x客户端。然后服务器没有从客户端收到任何东西,但客户端x连续打印的值。(System.out.println(data);)我试图从服务器向客户端发送动态值,但客户端只打印服务器第一次发送的值。

标签: javapythonsockets

解决方案


您不提供任何调试输出,因此很难 100% 确定这是全部原因。但是,您的客户端代码的这一部分似乎很明显是不正确的:

            while((character = reader.read()) != -1) {
                data.append((char) character);
            }
            System.out.println(data);

服务器永远保持连接打开(没有设置connected为假)。所以在上面的循环中,返回的字符reader.read永远不会是-1因为-1只在“流结束”时返回。仅当服务器关闭其套接字或以其他方式断开连接时才会发生流结束。

您应该添加对换行符的检查以跳出读取循环:

                if (character == '\n')
                     break; 

或者您可以将其添加到 while 条件:

           while ((character = reader.read()) != -1 && character != '\n') {
                 ...

您的代码总体上缺乏对可能的异常情况的适当处理。例如,如果客户端断开连接,您的服务器将永远不会退出其循环。它将调用recv,返回一个空字符串(表示连接上的“文件结束”),因此将正确绕过发送响应,但它会简单地返回并再次执行recv,再次获取一个空字符串,依此类推永远。

此外,您的 python 代码隐含地假设recv返回完全由客户端发送的单个字符串,这不能保证。例如,如果客户端发送一个 20 个字符的字符串,那么第一个服务器recv调用可能会返回前 10 个字符,而下一个调用会返回其余的。

(在实践中,考虑到客户端代码中的休眠,这在这段代码中不太可能成为问题,但是应该进行防御性编程,因为在真正的生产程序中,不可避免地会出现竞争或边缘情况。这会导致客户端和服务器不同步并且难以调试。)


推荐阅读