【发布时间】:2015-02-18 20:07:43
【问题描述】:
我希望我的问题的答案是指向文档的指针。但是,如果合适的话,我可以发布代码来寻找错误。
为了简化在家工作,我试图在单个 Wintel 操作系统/计算机中模拟将在微控制器中运行的服务器与将在 Wintel PC 中运行的 Java 客户端之间的交互。如果仿真足够好,我就不必将微控制器设备带回家只是为关系的 PC 端开发软件。
因此,在单个 Wintel 计算机(在家)中的单个 JVM 中,我这样做了:
- 创建了一个绑定到 192.168.1.63:3456 的新 ServerSocket 对象(本地 地址和本地(知名)端口),backlog 参数设置为 0。此对象 表示通常在微控制器中的代码。
- 创建了一个绑定到 192.168.1.63:3456 和 192.168.1.63:0(远程地址,远程端口,本地地址,本地 端口(临时端口的占位符))。这个对象代表 通常会在 Wintel 计算机中的代码/对象。
我预计上面第 2 项中新 Socket 的创建会阻塞(不连接),直到我调用 ServerSocket 的 accept() 方法。相反,Socket 创建尝试(以及 Socket 的隐式连接尝试)立即产生了一个新的(客户端)Socket 对象;我的(客户端)代码继续执行(接下来的几条指令是 .setReuseAddress(true)、.getInputStream()、.getOutputStream() 等)。
我在 Java API 文档中读到的所有内容都明确或隐含地表明,ServerSocket 的 accept() 调用允许 Sockets 完成连接到 ServerSocket 的过程(实际上是到 ServerSocket 创建的新 Socket ......);但是我的 Socket 在调用 ServerSocket accept() 之前就已经开始比赛了。
谁能指出我所看到的解释(客户端的连接尝试在服务器的 accept() 之前完成)?
希望解释能让我知道如何创建适当的模拟(不需要特殊代码,因为客户端和服务器都在一台计算机上)。
PS:以防万一……当我看到这种行为(上图)时运行的代码是单线程的。在有人指出它必须成为多线程才能完全成功之前;我知道。无论如何,我没想到我上面描述的。
【问题讨论】:
-
为什么会有问题?
-
@immibis, A) 任何关于我编写的代码如何执行的不理解都是一个问题(有时很小,有时很大)。 2)如果是bug,应该报告。 C)当 Socket 创建没有阻塞时,包含它的线程在服务器准备好之前开始尝试与服务器通信(这会破坏它们)。 D) 模拟服务器的行为方式与真实微控制器服务器的行为方式不同。 E) 我需要继续吗?
-
我在 Linux 上的 C 中得到了与您相同的结果。看起来您的答案在这个问题中:stackoverflow.com/q/2409277/3004881
-
丹·盖茨 - 谢谢。在 Stevens 的 Unix Network Programming Vol I 中,我还看到了这个有用的句子,“TCP 服务器调用accept 以从已完成的连接队列的前面返回下一个已完成的连接[Blake 说:积压](图 4.7)。 "我认为如果对 Java ServerSocket.accpt() 和 Socket() JavaDocs 进行修改以阐明接受调用从已完成连接的积压队列中提取已完成的连接(或块)(摆脱不良定义短语“未决连接”)。正式建议的简单方法是什么?
-
仅供参考 - 我使用 Oracle 的错误报告和功能请求流程来建议更新 ServerSocket API(和教程)文档。该建议在功能请求中。该请求已分配审核 ID:JI-9019201;并且标题为“ServerSocket.accept() API 描述应包括过去时”
标签: java sockets connect serversocket acceptance