我写了一个“推送服务器”,当客户端打开一个连接时,它会在服务器写入流时保持打开状态。我想知道如何编写一个Java客户端,它通过这种无限长的响应来接收命令。
问题是我不知道从哪里开始。如果你能指出我可以阅读Javadoc的课程方向,那就太棒了。我希望它能够立即响应,因此线程可能是必须的。
非常感谢您的帮助!
编辑:无限长度我指的是未知长度。无限一词用于强化连接通常永远不会被服务器关闭的点。并没有传输大量数据。
另一个编辑:也许有必要指出这是一个运行PHP脚本的HTTP服务器。
答案 0 :(得分:7)
如果它们是由换行符分隔的简单命令,那么滚动自己的客户端应该相当简单:
编辑: HTTP不是保持长期连接打开的最佳协议,您可能会遇到超时问题。下面的代码未经测试,但应该给你一个很好的起点。
编辑2:正如评论中所指出的,线程池在这里可能是必需的,也可能没有用。您应该注意,使用线程不会神奇地使事情变得更快或增加您可以处理的请求数量。使用线程池的好处是允许客户端在前一个命令仍在执行时立即接收新命令。如果处理命令需要一些I / O任务,例如,这可能是重要的。呼叫另一台服务器,但在你的情况下它可能有点过分。
ExecutorService svc = Executors.newCachedThreadPool();
URLConnection c =
new URL("http://192.168.1.122/push/out.php?nduid=1").openConnection();
c.setReadTimeout(30 * 60 * 1000); // Set the read timeout to 30 minutes
c.connect();
InputStream is = c.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String cmd = null;
while ((cmd = r.readLine()) != null) {
svc.execute(new Runnable() {
public void run() {
processCmd(cmd); // work happens here in a different thread.
}
});
}
is.close();
这里的关键是只要底层TCP连接保持打开,从套接字返回的输入流就会保持打开状态。客户端可以继续从流中读取,readLine
调用将根据需要直接阻塞,直到新数据到达。当readLine
返回null时,这意味着底层输入流遇到文件结尾,这反过来意味着服务器关闭了套接字。
获得完整的数据后,可以将其提交给线程池,以便在不同的线程中进行解析和执行。以这种方式打破工作使您可以专注于从单行文本解析和执行命令,这比尝试处理任意大量的数据流更易于管理。
答案 1 :(得分:-2)
如果您打开与服务器的连接,请检查服务器并使用while(server.isSending) { respond();}
,然后关闭连接?
示例:
//Connection to the server
openConnection();
while(server.isSending()) {
//Here can you respond in any way
respond();
}
您可能还必须使用InputStream。
我对InternetConnections的工作并不熟悉,但我希望你走上正确的轨道