如何使用Java Socket连接券商API(XTB)并正常获取响应?
现有实现的核心问题
- 缓冲流未触发实际发送
你使用的BufferedWriter自带本地内存缓冲区,调用write()写入的JSON内容会先暂存在本地缓存中,不会直接通过网络发送到服务端。没有执行flush()强制把缓存内容推送到网络链路,服务端根本收不到你的登录请求,自然不会返回任何响应。 - 缺少协议规定的消息结束标识
XTB XAPI的TCP通信规则要求,每段JSON格式请求必须以换行符\n作为消息结束标记,服务端识别到该标记后才会开始处理当前请求。你现在仅写入JSON字符串本身,没有追加结束标识,就算将缓存内容推送到网络,服务端也会一直等待你发送后续内容,不会触发响应返回。 - 读取逻辑和协议不匹配导致阻塞
你使用in.readLine()读取响应,该方法会一直阻塞等待,直到遇到换行符才返回读到的内容。但XTB的返回响应本身不一定携带换行终止符,会导致即使服务端已经把所有数据发回,程序也会卡在读取位置等不到换行,拿不到任何返回值。 - 无超时配置导致程序永久挂起
默认创建的Socket连接没有设置任何超时时间,一旦出现网络不通、服务端拒绝连接、请求格式不被识别的情况,程序会卡在读取操作的位置无限等待,既不报错也不退出,根本没法定位到底是连接没通、还是请求发出去后没被处理。 - 存在冗余无效代码
你初始化的InetSocketAddress a对象没有被任何逻辑使用,属于完全多余的代码片段,不影响运行但会增加逻辑混淆。
修正后的可运行实现
修正后的代码覆盖了上述所有问题,按照XAPI的通信逻辑完成请求发送和响应读取:
public static void main(String[] args) { String host = "xapi.xtb.com"; int port = 5112; // 提前构建JSON请求体 JSONObject main = new JSONObject(); JSONObject user = new JSONObject(); main.put("command", "login"); user.put("userId", "你的真实API用户ID"); user.put("password", "你的真实API密码"); main.put("arguments", user); try ( Socket s = new Socket() ) { // 设置10秒连接超时,避免永久卡在TCP连接阶段 s.connect(new InetSocketAddress(host, port), 10000); // 设置10秒读取超时,避免无限等待服务端响应 s.setSoTimeout(10000); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); // 写入请求JSON + 协议要求的换行结束符 out.write(main.toString()); out.newLine(); // 强制将缓冲区内容刷到网络链路,真正发送请求 out.flush(); // 循环读取响应内容,不依赖换行符判断传输结束 StringBuilder response = new StringBuilder(); String line; while ((line = in.readLine()) != null) { response.append(line); } System.out.println("服务端返回:" + response); } catch (IOException ex) { ex.printStackTrace(System.out); } }
额外排查注意点
- 确认端口和通信模式匹配:5112是无加密的TCP明文通道,6112是TLS加密通道,不要错用端口,也不要在无加密端口上发送TLS加密握手包。
- 替换代码中的占位符为真实凭证:原代码里的密码占位符
MY_PSSWD存在拼写错误,替换为你申请API权限后获取的真实测试账号密码即可。 - 如果调整后依然无响应,先检查本地防火墙是否放开了对应端口的出站权限,避免网络请求包被本地拦截。
内容的提问来源于stack exchange,提问作者Bartek Komendera
相关产品推荐
相关产品推荐

