java - 使用套接字将消息从 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);
)我试图从服务器向客户端发送动态值,但客户端只打印服务器第一次发送的值。
解决方案
您不提供任何调试输出,因此很难 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 个字符,而下一个调用会返回其余的。
(在实践中,考虑到客户端代码中的休眠,这在这段代码中不太可能成为问题,但是应该进行防御性编程,因为在真正的生产程序中,不可避免地会出现竞争或边缘情况。这会导致客户端和服务器不同步并且难以调试。)
推荐阅读
- python - python3,如何下载zip文件
- java - 使用 FlyingSaucer (Itext5) 使图像居中的问题:“margin:auto and display block”并从 XHTML 解析为 PDF
- powershell - 索引为 [-1] 的数组
- bash - 如何将数据发送到 /dev/ttyAT 端口并查看答案?
- opencart - 如何在管理员 opencart 3 中创建自定义页面
- python - 从 Python 访问 IntelliJ 数据库
- typescript - Reflect.decorate VS 在 TypeScript 中手动进行装饰
- sql - 在 SQL Server 中使用逗号分隔值的 Like 运算符
- docker - traefik logrotate 访问日志 docker 卷
- amazon-web-services - 使用 CloudFormation(和 Lambda 轮换模板)的 Aurora Serverless 密码轮换设置