getbytes方法_java 输入流的read方法不返回 http请求头 keep-alive wireshark

写一个模拟浏览器的时候,使用inputstream的read方法读取服务器这边的数据时,发现一直不返回。

代码如下:

public static void main(String[] args) throws IOException {
		InputStream inputStream = null;
		OutputStream outputStream = null;
		Socket socket = null;
		try {
			socket = new Socket("120.78.55.19", 80);

			inputStream = socket.getInputStream();
			outputStream = socket.getOutputStream();
			outputStream.write("GET / HTTP/1.1n".getBytes());
			outputStream.write("HOST:120.78.55.19n".getBytes());
			outputStream.write("n".getBytes());
			int i = inputStream.read();
			while (i != -1) {
				System.out.print((char) i);
				i = inputStream.read();
				System.out.print("好");
			}
			System.out.println("跳出while循环");

		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			System.out.println("进入finally");
			if (null != inputStream) {
				inputStream.close();

			}
			System.out.println("关掉了in");
			if (null != outputStream) {
				outputStream.close();

			}
			System.out.println("关掉了out");
			if (null != socket) {
				socket.close();

			}
			System.out.println("关掉了socket");
		}
		System.out.println(socket);
	}

也就是这里是模仿了浏览器发送的http请求,请求服务端的网页。然后情况是:

网页数据都返回了,可是程序却一直没关闭。然后分析了一波,发现是停在了inputstream的read方法了。然后看read方法的注释:

Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.

也就是从输入流中获得下一个字节的数据,返回的是一个在0到255的int类型的值。如果因为字节流到了尽头而没有字节了,就返回-1.这个方法会阻塞直到有输入数据,或者到达输入流的尽头,或者发送异常。

理解起来也很简单,就是一个输入流,read是按字节进行读取的,将一个8bit按ascii码读取为整数,如果读的是文本,那么会有文本结束符,遇到结束符姐返回。

下面是我的分析思路:

我刚开始以为服务端这边返回完数据之后就会结束,后来检测到并没有结束,没想明白,然后开个wireshark对数据进行分析,没想到过了大约75秒后,read方法返回了,然后结束了程序。与此同时,wireshark中也有了反应,此时刚好是服务端和客户端的tcp的4次挥手结束。如下图:

174ee0c866096037de260ec8d2a22057.png

这里我是试了两次,大家看下面一次即可。即8到14部分。这里只显示了服务端向客户端发送的数据。刚开始是tcp的三次握手,然后是发送http信息,然后停了75s左右的时间,就出现了后面的tcp的4次挥手。

此时我反应过来,inputstream的read方法在socket中是面向的是一次的tcp连接。并不是一次的http传输。

这里我有发现这和http的请求头重的connection=keeplive有关。

我们先来了解一下这个请求头的作用:

参考维基百科:

HTTP持久连接(HTTP persistent connection,也称作HTTP keep-alive或HTTP connection reuse)是使用同一个TCP连接来发送和接收多个HTTP请求/应答,而不是为每一个新的请求/应答打开新的连接的方法。

在 HTTP 1.0 中, 没有官方的 keepalive 的操作。通常是在现有协议上添加一个指数。如果浏览器支持 keep-alive,它会在请求的包头中添加:

Connection: Keep-Alive

然后当服务器收到请求,作出回应的时候,它也添加一个头在响应中:

Connection: Keep-Alive

这样做,连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个连接。这一直继续到客户端或服务器端认为会话已经结束,其中一方中断连接。

在 HTTP 1.1 中 所有的连接默认都是持续连接,除非特殊声明不支持。HTTP 持久连接不使用独立的 keepalive 信息,而是仅仅允许多个请求使用单个连接。然而, Apache 2.0 httpd 的默认连接过期时间是仅仅15秒,对于 Apache 2.2 只有5秒。 短的过期时间的优点是能够快速的传输多个web页组件,而不会绑定多个服务器进程或线程太长时间

优势

  • 较少的CPU和内存的使用(由于同时打开的连接的减少了)
  • 允许请求和应答的HTTP管线化
  • 降低拥塞控制 (TCP连接减少了)
  • 减少了后续请求的延迟(无需再进行握手)
  • 报告错误无需关闭TCP连接

劣势

对于现在的广泛普及的宽带连接来说,Keep-Alive也许并不像以前一样有用。web服务器会保持连接若干秒(Apache中默认15秒),这与提高的性能相比也许会影响性能。[7]

对于单个文件被不断请求的服务(例如图片存放网站),Keep-Alive可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。

然后再回到我们的问题来:我是使用nginx搞在服务器上,nginx上默认这个keep-live的时间为75s. 我感觉了一下,大约也就这个时间就断开tcp连接,然后我的read方法就返回了。

然后,忽然醒悟,原来是这样啊。关键还是看服务器那边怎么配置啊。

http只是一次请求,read是看这个tcp连接断开了没。前面我们分析过,socket其实就是在tcp层上的数据传输。如果你自己写一个服务器,然后不设置对keep-alive的反应,那你就会发现,即使浏览器keep-alive了,也是一连上来就直接断了。对计算机网络的理解,感觉达到tcp的字节上就算有了一些基本的认识了。

唉,还是太年轻了。

欢迎交流讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值