URL.openConnection() 第二次返回已打开的连接

4

我正在使用Scala开发一个网站抓取应用程序。我要抓取的网站非常依赖于会话,因此在执行任何其他操作之前,我必须先访问网站以获取会话ID。

我通过以下方式获取用于检索会话ID的连接:

url.openConnection().asInstanceOf[HttpURLConnection]

它可以正常工作。返回的HttpURLConnection的“connected”字段是false,当我在其上调用.connect()时,它会变为true。没有问题。

第一个麻烦的迹象出现在我完成连接并调用.disconnect()后。连接字段仍保持为true. 嗯。

因此,我现在已经获得了我的会话ID,并且我要获取页面上的表单。我调用

url.openConnection().asInstanceOf[HttpURLConnection]

和上次一样,实际上是同样的代码,但这一次给我的HttpURLConnection却将.connected字段设置为true!起初我以为它以某种方式再次给了我相同的对象,但不,内存ID是不同的。

因此,当我在连接上调用.setRequestProperty()时,它会因IllegalStateException而崩溃:已经连接。

我是否误解了如何使用HttpURLConnection?

注:Scala 2.9.2,Java 6.0。另外,我调用.openConnection()的URL对象是不同的对象,而不是相同的对象。

谢谢...


1
我有同样的问题。奇怪的是,它似乎发生在某些虚拟机上而不是其他虚拟机上 - 我还没有发现规律。你找到解决方法了吗? - slim
3个回答

1

这被称为连接池,在寻求HTTP Keep-alive的过程中。它很好,你需要它。如果你真的不需要它,就调用disconnect()方法。


我正在调用.disconnect():请参见原始帖子。它会奇怪地保留.connected字段不变。 - Dan Wiebe
我并不反对我的HttpURLConnection被池化:我只是希望能够在连接多次后设置请求参数。 - Dan Wiebe
@DanWiebe 如果那不起作用,我会感到惊讶的,因为这是一个非常基本的使用模式。 - user207421

1

URL类在我的经验中不太适合基于会话的工作(特别是基于cookie的会话)。

如果您想利用这一点,我建议使用类似Apache HTTPClient的东西。

在我看来。


会话不是基于 cookie 的,而是基于参数的。如果可能的话,我想保持它相对轻量级。我的操作足够简单,我不想引入像 HTTPClient 这样的重型工具。 - Dan Wiebe
没问题,这只是一个建议 :) - MadProgrammer
我不同意这个评论。当重定向时,URLConnection处理cookie的方式不正确,但除此之外它工作得很好。我已经做了相当多的工作(例如http://www.bigbeeconsultants.co.uk/bee-client),并且是通过艰苦的方式发现这一点的。如果你对其强制线程池感到满意,那么Apache API可能是一个很好的爬虫工具选择。 - Rick-777
@Rick-777 好知道,我从来没能让它正常工作,一定做错了什么。 - MadProgrammer

0

听起来像是HttpUrlConnection在幕后保持连接活动

阅读这篇文章以获取一些提示,强制它关闭连接并不过度帮助。

虽然在您的情况下,听起来您可能想要使用keep-alive,因为它可以通过避免不必要的连接握手来加速您对网站的调用。


谢谢你的回复!我试过了:.setRequestProperty("Connection", "close")。但是没有起作用,还是一样的问题。不过,我很感谢你的建议。 - Dan Wiebe
你是否也在读取连接时关闭了任何流? - matt b
是的,当然没问题,但还是谢谢你的检查。在任何情况下,似乎都无法原谅您要求一个新的HttpURLConnection,却得到一个已经连接的。我想不出任何情况下这应该是可以接受的。 - Dan Wiebe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接