【问题标题】:Keep TCP socket-connection alive if no data is currently available如果当前没有可用数据,则保持 TCP 套接字连接处于活动状态
【发布时间】:2014-07-14 06:01:47
【问题描述】:

我已经实现了一个小型 HTTP 服务器,它允许客户端通过 HTTP 连接并将音频数据流式传输给它们。

我的问题是,如果当前没有可用的音频数据,连接似乎会中断,要么是因为客户端断开连接,要么是由于 Android 内部的其他原因。

我的行为方式如下:

serverSocket = new ServerSocket(0);
Socket socket = serverSocket.accept();
socket.setKeepAlive(true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

out.write("HTTP/1.1 200 OK\r\n");
out.write("Content-Type: audio/wav\r\n");
out.write("Accept-Ranges: none\r\n");
out.write("Connection: keep-alive\r\n"); // additionally added due to answer below
out.write("\r\n");
out.flush();
..
while(len=otherInput.read(audioBuffer)){
 out.write(audioBuffer, 0, len);)
}

当然,这只是真实代码的片段,但它显示了我在做什么。 现在,如果“otherinput.read()”由于目前没有可用数据而需要很长时间,我会得到一个

java.net.SocketException: sendto failed: EPIPE (Broken pipe)
    at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:499)
    at libcore.io.IoBridge.sendto(IoBridge.java:468)
    at java.net.PlainSocketImpl.write(PlainSocketImpl.java:508)
    at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:46)
    at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:270)
    at java.io.BufferedOutputStream.flushInternal(BufferedOutputStream.java:185)
    at java.io.BufferedOutputStream.write(BufferedOutputStream.java:139)

谁能告诉我如何在没有手动心跳的情况下防止连接中断/关闭?我错过了一些标题还是我使用了错误的方式?

提前感谢您的帮助,同时疯狂地尝试和搜索自己。

【问题讨论】:

    标签: java android serversocket keep-alive


    【解决方案1】:

    这里至少有两个问题。

    1. HTTP 服务器的客户端不像您预期​​的那样表现良好。考虑一个浏览器。用户可以随时关闭、返回、导航离开等,甚至在页面加载过程中也是如此。如果您在传输到客户端时遇到任何错误,除了关闭连接并忘记它之外,您无能为力。这同样适用于任何服务器,但它适用于 HTTP 服务器。

    2. 您没有读取客户端发送的整个请求。您需要读取所有标题直到一个空行,然后您需要读取正文直到 Content-length: 标题中指定的长度,或所有块,或直到流结束,视情况而定:见RFC 2616。这样做的影响可能是您导致在 (1) 处的行为。

    【讨论】:

    • 感谢您的评论。 #1 肯定是完全正确的,而我的客户是 DLNA 渲染器。如果长时间没有数据传输,他们可能会自行关闭通道,但我仍然认为这是服务器端的问题。关于#2,我正在读取来自客户端的整个输入,并且正在评估标头等。这只是我没有在上面的代码中添加的内容。总的来说也是完全正确的。我担心这可能是与 Android 有关的问题,因为我在搜索此类/此问题时总是绊倒 Android-tickets:/ 再次感谢您的提示!
    猜你喜欢
    • 2019-09-01
    • 2012-07-08
    • 2018-04-13
    • 2014-03-24
    • 1970-01-01
    • 2013-09-23
    • 2012-01-03
    • 2021-09-13
    • 2013-08-27
    相关资源
    最近更新 更多