2011-11-09 58 views
3

我已经构建了一个简单的Java程序,可以在本地作为服务器使用。保持来自自制Java服务器的持续连接

在它做了一些事情,比如预览目录的那一刻,转发到index.html的,如果目录中包含它,发送Last-Modified头和正确地响应客户端的请求If-Modifed-Since

我现在需要做的是让我的程序接受持久连接。它目前是线程化的,这样每个连接都有自己的线程。我想把我的整个线程代码放在一个循环中,直到Connection: close或指定的超时。

有没有人有任何想法从哪里开始?

编辑:这是一个大学项目,必须在没有使用框架的情况下完成。

我有一个无限循环的主要方法,每次循环它创建一个Socket对象,然后创建一个HTTPThread对象(我自己创建的一个类) - 处理单个请求。

我想允许多个请求在单个连接内使用Connection: keep-alive请求标头进行工作。我期望在我的HTTPThread类中使用循环,我只是不确定如何传递多个请求。

感谢提前:)

+0

你能再解释一下,当你说“持续连接”时,你的意思是什么?如果会话临时断开连接,您是否可以保存会话状态以恢复会话状态? – AlexR

+0

我的问题是我不完全明白我需要做什么!目前我有一个循环调用一个名为HTTPThread的类。它传递一个inputStream和一个outputStream。 HTTPThread类然后相应地解析请求。如果连接状态是保持活动状态,我想以某种方式使用我已经有的下一个请求的连接。 – Alex

回答

1

我假设你正在实施的HTTP协议的代码自己开始与Socket API的应用。而且你正在实现HTTP规范的持久连接部分。

您可以按照您的建议将代码放入循环中,然后使用Socket.setSoTimeout设置阻塞操作的超时时间,从而设置HTTP超时时间。除了不关闭它们之外,您不需要为连接重新使用流而做任何事情。


我会指出有更简单的方法来实现Web服务器。有许多现有的Java Web服务器框架和应用程序服务器,或者您可以重新使用Apache HTTP协议栈。

+0

我有一个循环当前为每个请求声明一个套接字。一个HTTPThread对象(我的所有代码都在这里)接受一个输入流和一个输出流,并在那里处理单个请求。我怎么能从HTTPThread类中执行多个请求 - 单个连接? – Alex

+0

soTimeout与持续连接有什么关系? – Kevin

+0

如此处所述,http://en.wikipedia.org/wiki/HTTP_persistent_connection,HTTP 1.1始终使用持久连接,除非标头中另有说明。 Apache 2.2在闲置5秒后关闭套接字。所以你必须不关闭套接字,而且还要设置一些定时器来关闭它,如果它闲置太久的话。做到这一点的一种方法是有一个专门的管理线程来处理这个(也许是其他的)任务。 – Kevin

0
  1. 如果它应该像一个Web服务:从客户端打开2个插槽,一个用于请求,一个用于 响应。保持插座和流路畅通无阻。

    您需要定义一个分隔符来通知对方一个 传输结束。二进制的特殊位字符串,用于基于文本的协议(如XML)的特殊 字符(通常是换行符)。

  2. 如果您确实尝试实施自己的http服务器,则应该使用已实施HTTP 1.1连接保持标准的library
+0

它的功课我怀疑正确的解决方案是使用已经做到这一点的图书馆。 – Kevin

+0

我明白了,那么你当然应该自己实现它。 ;)Java Socket API提供了一种设置SO_KEEPALIVE的方法:http://download.oracle.com/javase/6/docs/api/java/net/Socket.html#setKeepAlive(boolean) – Stephan

+0

我认为保持活力一个套接字不同于HTTP 1.1持久连接。 – Kevin

0

一些想法,让你开始:

此Wikipedia文章介绍了HTTP 1。1个持久连接:

http://en.wikipedia.org/wiki/HTTP_persistent_connection

你想不关闭套接字,但一些不活跃一段时间后(Apache 2.2的使用5秒)要关闭它。

你有两种方法来实现:

  1. 在你的线程不关闭套接字,不退出线程,而是把一个读超时插座上(无论你想支持)。当你调用读取它会阻塞,如果超时过期,那么你关闭套接字,否则你读下一个请求。这样做的缺点是每个持久连接都可以保持一个线程和一个套接字,无论你的最大等待时间是多少。这意味着您的解决方案无法扩展,因为您持有太久的线程(但对于学校项目而言可能没问题)!

  2. 通过维护一个元组列表({socket,timestamp},拥有一个后台线程监视器并关闭超时连接并使用NIO在现有的open上检测一个新读取来解决(1)插座。因此,在完成读取初始请求之后,您只需退出该线程(将其返回到线程池)。显然这更复杂,但它具有释放请求线程的好处。

+0

请原谅我的无知,但你如何阅读下一个请求..我认为这就是我被卡住的地方。另外,在任何时候,我都不会调用关闭套接字的方法,关闭输入和输出流,是否也会做同样的事情? – Alex

+0

在哪种情况下您有兴趣?在第一种情况下,您将读入输入流并阻塞,直到客户端发送另一个请求,或发生超时,或者客户端强制关闭连接。在第二种情况下,您对非阻塞IO apis执行相同的操作,这意味着读取会立即返回,但是当流中有新数据可用时,您可以从某个选择循环中找到该循环,该循环运行在不同的线程中。 – Kevin

+0

如果关闭套接字,它也会关闭输入和输出流。 – Kevin