必须在子线程中执行网络操作,不然会抛出异常
我已验证:
url.openConnection()不会进行物理网络连接: netstat看不到有连接!
HttpURLConnection.connect()会进行物理网络连接: netstat能看到有连接ESTABLISHED(如果没有进行disconnect())。如果disconnect(),那就来不及看了。
(1)不写connect(),直接用getInputStream()是可以的,它发现没有连接的话,会默认先进行connect()
(2)先connect(),再getResponseMessage(),再getInputStream(),是可以的
(3)看源文件,getResponseCode() 里会先getInputStream(),说明会默认先进行连接,再得到responsecode。 因为responsecode其实也是网站发来的数据中的一部分。
URL中的端口可以这样: URL url=new URL("http://192.168.0.63:8888"); ,这样是连接8888端口
HttpURLConnection connection =(HttpURLConnection) url.openConnection(); ,不会进行网络连接,只是生成URLConnection对象
↓
对HttpURLConnection对象(http头)进行配置(一堆set函数)
↓
对outputStream流(请求正文)写入(写入的东西不会发送到网络,而是存在于缓冲区中)
↓
connect():会根据配置值生成http头部信息,并进行TCP网络连接
↓
getInputStream():把请求(http头+请求正文)正式发送出去,并得到输入流(网站发来的数据)。它得到的是数据正文。数据头信息可以用getResponseCode()等来得到。
引用网友说的:
a HttpURLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
b 在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,对connection对象的一切配置(那一堆set函数) 都必须要在connect()函数执行之前完成。
而对outputStream的写操作,又必须要在inputStream的读操作之前。
这些顺序实际上是由http请求的格式决定的。
如果inputStream读操作在outputStream的写操作之前,会抛出例外:
java.net.ProtocolException: Cannot write output after reading input.......
c http请求实际上由两部分组成,一个是http头,所有关于此次http请求的配置都在http头里面定义,一个是正文content。
connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,就必须把所有的配置准备好。
d 在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。
至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。
由于http请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)都是没有意义的了,执行这些操作会导致异常的发生。
connect()方法:打开到此URL引用的资源的通信链接(如果尚未建立这样的连接)。如果在已打开连接(此时connected字段的值为true)的情况下调用connect方法,则忽略该调用。
URLConnection对象经历两个阶段:首先创建对象,然后建立连接。在创建对象之后,建立连接之前,可指定各种选项(例如,doInput和UseCaches)。连接后再进行设置就会发生错误。连接后才能进行的操作(例如getContentLength()),将隐式地先执行连接。
所以,有的方法会隐式地执行connect()方法。conn.openInputStream();//隐式执行了connect方法。此方法的实现sun.net.www.protocol.http.HttpURLConnection.getInputStream好像没有开源。
It should be noted that a URLConnection instance does not establish the actual network connection on creation. This will happen only when calling {@linkplain java.net.URLConnection#connect() URLConnection.connect()}.
openConnection只是创建了,还没有正式的连接到远程。调用connect,才开始打开连接,发出请求!
url.openconnection();方法原形:public URLConnection openConnection()。返回一个 URLConnection 对象。如果 URL 的协议(例如,HTTP 或 JAR)存在属于以下包或其子包之一的公共、专用 URLConnection 子类:java.lang、java.io、java.util、java.net,返回的连接将为该子类的类型。例如,对于 HTTP,将返回 HttpURLConnection,对于 JAR,将返回 JarURLConnection。
可以看出:url对象用openconnection()获得URLConnection类对象,再用URLConnection类对象的connect()方法进行连接。
测试:
import java.net.URL;
import java.net.HttpURLConnection;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
new Thread(new Runnable()
{
@Override
public void run()
{
String str="";
String g_str="";
HttpURLConnection connection=null;
try
{
URL url=new URL("http://192.168.0.63:8888");
connection =(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000); //如果超时,则会抛出异常
connection.setReadTimeout(8000);
InputStream in=connection.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
StringBuilder sb=new StringBuilder();
while((str=reader.readLine())!=null) sb.append(str);
g_str+=sb.toString();
}
catch(Exception e)
{
//e.printStackTrace();
g_str=e.toString();
}
finally
{
if(connection!=null) connection.disconnect();
}
}
//这里可以对g_str进行处理了
}).start();
文章评论(0条评论)
登录后参与讨论