network-URLConnection
1. URLConnection 对象的创建过程
摘自 rfc7230
If the port subcomponent is empty or not given, TCP port 80 (the reserved port for WWW services) is the default.
Http 协议默认 80 端口
1 | // URLConnection 的使用。 |
可以使用 wireshark 工具来分析上面代码中出现的网络请求。
1 | // 过滤 http 协议中主机是 "cnblogs.com" 的流量 |
2. 实现
openConnection
URL 的 openConnection 方法,最终是创建了一个 sun.net.www.protocol.http.HttpURLConnection
类,这个类继承自 java.net.HttpURLConnection
connect
HttpURLConnection 的 connect
方法则负责创建一个 sun.net.www.http.HttpClient
对象。
然后调用这个 HttpClient 对象的 openServer 方法。
openServer方法,将创建一个 Socket
对象。并调用 Socket
的 connect
方法和 URL 中指定的 <server, port> 建立 socket 连接。
1 | // HttpClient 创建过程中,最终调用 openServer 方法 |
getInputStream
下面的整个过程是阻塞的,就是使用 socket 的 InputStream 的 read 方法进行数据的读取。
1. 初始化 HTTP 请求头
将请求参数封装到 MessageHeader 对象中。
2. 发送 HTTP 请求
使用上面的 serverOutput 将 MessageHeader 输出
3. 等待 HTTP 响应
将响应数据解析出来,封装到 HttpInputStream
对象中和 MessageHeader
对象中
MessageHeader 存储 Http 响应头信息
HttpInputStream 存储传输过来的数据
4. 返回 InputStream
返回上面解析好的 HttpInputStream
Http 关闭连接
Http 的超时
URLConnection 有下面两个方法。用来设置连接超时时间和,socket读取超时时间。
- setConnectTimeout
- setReadTimeout
这两个方法最终调用 HttpClient 类所持有的 Socket 方法的 setSoTimeout 来设置超时。
而 setSoTimeout 方法的实现,则是调用系统的 socket API setsockopt
来设置 SO_RCVTIMEO
和 SO_SNDTIMEO
进行超时设置。
If the timeout is set to zero (the default) then the operation will never timeout.
对于 URLConnection 的实现来说,其默认的超时值就是 0, 所以也就是不会超时。
Keep-Alive 保持连接。可以让一个请求连接,被复用多次。当创建一个 HTTP 请求的时候,其底层对应的是一个 TCP 连接。在 http 1.0 时,一个 http 响应完成之后其所对应的 tcp 连接就立即释放了。
但是,对于一个页面,可能出现大量的资源需要请求,例如图片,js, css 等等文件。所以创建的 tcp 可以被复用的。因为创建一个tcp连接也是非常的耗时和耗费资源的。所以使用 keep-alive 来保持一个连接。