0

我正在尝试在 java 中实现一个简单的服务器应用程序。

它所做的一切都是在 tcp/ip 上的消息中读取并将其存储为字符串,这是我的代码。

    try{
        in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    } catch (IOException e) {
        System.out.println("cannot open input buffer");
        System.exit(-1);
    }

    clientSocket.setSoTimeout(5000);

    //read first bit of message
    message = in.readLine();
    System.out.println(message);
    //as message is an undefined length we need to loop and check for the springer miller 
    //end mark /Request
    while(message.contains("/Request") == false  )
    {
        try {
        message = in.readLine();
        System.out.println(message);
        }
        catch (IOException e) {
            System.out.println("cannot open input buffer");
            System.exit(-1);
        }
    }       

    //reply
    out.println(outputLine);

我遇到的问题是该消息似乎没有EOF。这是我正在翻译成我的另一家公司的协议,这就是程序的目的,所以我不能在消息中添加 EOF

如果我运行程序,得到的信息是:

POST / HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: http://htng.org/1.1/Listener.Wsdl#ReceiveMessageAsync
User-Agent: Java/1.6.0_24
Host: 192.168.0.32:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 3009

然后它在应该读取消息正文时挂起。

我以前从未使用过java,也不想写一个二进制套接字来检测我自己的EOF。

有没有办法读取 x 秒然后返回

感谢您的任何帮助。

PS 已经用 C++ 成功构建了程序,但需要移植到 java,因为目标机器未知。

4

2 回答 2

1

BufferedReader.readline将在 EOF 上返回 null 并且不会引发异常。

此外,“其他公司协议”似乎是 SOAP over HTTP。也许您想使用 HTTP 或 SOAP 库?这里的其他人将能够指点...

否则,您可以使用以下方法: readLine once 以检查该方法是否确实是 POST (否则 Content-Length 标头可能不存在)并且路径是否正确。
readLine 直到它返回一个空行(或 null),以读取所有 HTTP 标头。在执行此操作时,请注意以 Content-Length 开头的行,以确定以下 XML 数据的长度。创建一个正确长度的 char[] 并用于in.read(cbuf, 0, cbuf.length)将 xml 读入创建的缓冲区 cbuf。

于 2011-03-31T16:19:03.760 回答
0

在 TCP/IP 之上实现协议很棘手,并且需要对网络、套接字和您的操作系统 I/O 的工作方式有相当多的了解。

此外,在网络复杂性之上,实现 HTTP 非常复杂。

我礼貌地建议您可能陷入困境,因为您必须在这个级别提出问题,并且可能需要比您在 SO 上获得的更多帮助。

...反正。

如果您正在读取的服务器正在尝试与 http 通信,请使用现有组件。Apache HttpComponents 可能是个不错的选择。我真的不相信它会伪造 http 标头,我建议您跳过“轻量级”方法。

这是一些网络 I/O 的基本事实。

网络写入是面向数据包的。Tcp/ip 通常会尝试将尽可能多的内容填充到每个数据包中(使用一些智能算法)。这意味着,如果您写入 4000 字节,则消息将被分成几个任意大小的数据包,但通常小于 1500 字节 - 取决于网络设备。这也意味着如果您写入的数据包少于一个数据包,您的写入数据可能会合并到一个数据包中。(数据包也可以沿途拆分和合并。)

为了通过流发送消息(它本身以数据包的形式传输......),您需要提前知道消息的长度,或者读取一个完整的数据包(执行 .read() 到一个大缓冲区),解析内容,并以某种智能方式提取和构造完整的消息。正是http的作用。(其中)

TCP/IP 肯定不是面向行的,所以你的换行符完全被忽略了。HTTP 使用内容长度(以及一些其他技巧,因为它可能并不总是被定义)通过单个 tcp/ip 流发送“消息”,当消息完全发送时,该流可能会或可能不会关闭。

于 2011-03-31T19:13:48.657 回答