[Android] HttpURLConnection & HttpClient & Socket

 

 

Android的三种网络联接方式
1、标准Java接口:java.net.*提供相关的类
//定义地址
URL url = new URL("http://www.google.com");
//打开连接
HttpURLConnection http = (HttpURLConnection) url.openConnection();

2、Apache接口:android.net.http.*
//DefaultHttpClient表示默认属性
HttpClient httpClient = new DefaultHttpClient();
//HttpGet实例
HttpGet get = new HttpGet("http://www.google.com");
HttpResponse rp = httpClient.execute(get);
其中post的方式请求步骤比较复杂

3、Android接口:android.net.*
//IP地址
InetAddress inetAddress = InetAddress.getByName("192.168.1.1");
//端口
Socket client = new Socket(inetAddress,61203,true);
//取得数据
InputStream in = client.getInputStream();
OutputStream out = client.getOutputStream();

Android网络连接之HttpURLConnection和HttpClient

转 http://www.cnblogs.com/devinzhang/archive/2012/01/17/2325092.html

1.概念      

      HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能:HttpURLConnection。但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。

      除此之外,在Android中,androidSDK中集成了Apache的HttpClient模块,用来提供高效的、最新的、功能丰富的支持 HTTP 协议工具包,并且它支持 HTTP 协议最新的版本和建议。使用HttpClient可以快速开发出功能强大的Http程序。

2.区别

HttpClient是个很不错的开源框架,封装了访问http的请求头,参数,内容体,响应等等,

HttpURLConnection是java的标准类,什么都没封装,用起来太原始,不方便,比如重访问的自定义,以及一些高级功能等。

 

URLConnection

HTTPClient

Proxies and SOCKS

Full support in Netscape browser, appletviewer, and applications (SOCKS: Version 4 only); no additional limitations from security policies.

Full support (SOCKS: Version 4 and 5); limited in applets however by security policies; in Netscape can't pick up the settings from the browser.

Authorization

Full support for Basic Authorization in Netscape (can use info given by the user for normal accesses outside of the applet); no support in appletviewer or applications.

Full support everywhere; however cannot access previously given info from Netscape, thereby possibly requesting the user to enter info (s)he has already given for a previous access. Also, you can add/implement additional authentication mechanisms yourself.

Methods

Only has GET and POST.

Has HEAD, GET, POST, PUT, DELETE, TRACE and OPTIONS, plus any arbitrary method.

Headers

Currently you can only set any request headers if you are doing a POST under Netscape; for GETs and the JDK you can't set any headers. 
Under Netscape 3.0 you can read headers only if the resource was returned with a Content-length header; if no Content-length header was returned, or under previous versions of Netscape, or using the JDK no headers can be read.

Allows any arbitrary headers to be sent and received.

Automatic Redirection Handling

Yes.

Yes (as allowed by the HTTP/1.1 spec).

Persistent Connections

No support currently in JDK; under Netscape uses HTTP/1.0 Keep-Alive's.

Supports HTTP/1.0 Keep-Alive's and HTTP/1.1 persistence.

Pipelining of Requests

No.

Yes.

Can handle protocols other than HTTP

Theoretically; however only http is currently implemented.

No.

Can do HTTP over SSL (https)

Under Netscape, yes. Using Appletviewer or in an application, no.

No (not yet).

Source code available

No.

Yes.

3.案例

URLConnection

复制代码
    String urlAddress = "http://192.168.1.102:8080/AndroidServer/login.do";  
URL url;
HttpURLConnection uRLConnection;
public UrlConnectionToServer(){

}
    //向服务器发送get请求
public String doGet(String username,String password){
String getUrl = urlAddress + "?username="+username+"&password="+password;
try {
url = new URL(getUrl);
uRLConnection = (HttpURLConnection)url.openConnection();
InputStream is = uRLConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String response = "";
String readLine = null;
while((readLine =br.readLine()) != null){
//response = br.readLine();
response = response + readLine;
}
is.close();
br.close();
uRLConnection.disconnect();
return response;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
 
    //向服务器发送post请求
public String doPost(String username,String password){
try {
url = new URL(urlAddress);
uRLConnection = (HttpURLConnection)url.openConnection();
uRLConnection.setDoInput(true);
uRLConnection.setDoOutput(true);
uRLConnection.setRequestMethod("POST");
uRLConnection.setUseCaches(false);
uRLConnection.setInstanceFollowRedirects(false);
uRLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
uRLConnection.connect();

DataOutputStream out = new DataOutputStream(uRLConnection.getOutputStream());
String content = "username="+username+"&password="+password;
out.writeBytes(content);
out.flush();
out.close();

InputStream is = uRLConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String response = "";
String readLine = null;
while((readLine =br.readLine()) != null){
//response = br.readLine();
response = response + readLine;
}
is.close();
br.close();
uRLConnection.disconnect();
return response;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
复制代码

HTTPClient

复制代码
String urlAddress = "http://192.168.1.102:8080/qualityserver/login.do";  
public HttpClientServer(){

}

public String doGet(String username,String password){
String getUrl = urlAddress + "?username="+username+"&password="+password;
HttpGet httpGet = new HttpGet(getUrl);
HttpParams hp = httpGet.getParams();
hp.getParameter("true");
//hp.
//httpGet.setp
HttpClient hc = new DefaultHttpClient();
try {
HttpResponse ht = hc.execute(httpGet);
if(ht.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
HttpEntity he = ht.getEntity();
InputStream is = he.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String response = "";
String readLine = null;
while((readLine =br.readLine()) != null){
//response = br.readLine();
response = response + readLine;
}
is.close();
br.close();

//String str = EntityUtils.toString(he);
System.out.println("========="+response);
return response;
}else{
return "error";
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "exception";
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "exception";
}
}

public String doPost(String username,String password){
//String getUrl = urlAddress + "?username="+username+"&password="+password;
HttpPost httpPost = new HttpPost(urlAddress);
List params = new ArrayList();
NameValuePair pair1 = new BasicNameValuePair("username", username);
NameValuePair pair2 = new BasicNameValuePair("password", password);
params.add(pair1);
params.add(pair2);

HttpEntity he;
try {
he = new UrlEncodedFormEntity(params, "gbk");
httpPost.setEntity(he);

} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

HttpClient hc = new DefaultHttpClient();
try {
HttpResponse ht = hc.execute(httpPost);
//连接成功
if(ht.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
HttpEntity het = ht.getEntity();
InputStream is = het.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String response = "";
String readLine = null;
while((readLine =br.readLine()) != null){
//response = br.readLine();
response = response + readLine;
}
is.close();
br.close();

//String str = EntityUtils.toString(he);
System.out.println("=========&&"+response);
return response;
}else{
return "error";
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "exception";
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "exception";
}
}
复制代码

servlet端json转化: 

复制代码
        resp.setContentType("text/json");  
resp.setCharacterEncoding("UTF-8");
toDo = new ToDo();
List<UserBean> list = new ArrayList<UserBean>();
list = toDo.queryUsers(mySession);
String body;

//设定JSON
JSONArray array = new JSONArray();
for(UserBean bean : list)
{
JSONObject obj = new JSONObject();
try
{
obj.put("username", bean.getUserName());
obj.put("password", bean.getPassWord());
}catch(Exception e){}
array.add(obj);
}
pw.write(array.toString());
System.out.println(array.toString());
复制代码

android端接收:

复制代码
String urlAddress = "http://192.168.1.102:8080/qualityserver/result.do";  
String body =
getContent(urlAddress);
JSONArray array = new JSONArray(body);
for(int i=0;i<array.length();i++)
{
obj = array.getJSONObject(i);
sb.append("用户名:").append(obj.getString("username")).append("\t");
sb.append("密码:").append(obj.getString("password")).append("\n");

HashMap<String, Object> map = new HashMap<String, Object>();
try {
userName = obj.getString("username");
passWord = obj.getString("password");
} catch (JSONException e) {
e.printStackTrace();
}
map.put("username", userName);
map.put("password", passWord);
listItem.add(map);

}

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

if(sb!=null)
{
showResult.setText("用户名和密码信息:");
showResult.setTextSize(20);
} else
extracted();

//设置adapter
SimpleAdapter simple = new SimpleAdapter(this,listItem,
android.R.layout.simple_list_item_2,
new String[]{"username","password"},
new int[]{android.R.id.text1,android.R.id.text2});
listResult.setAdapter(simple);

listResult.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
int positionId = (int) (id+1);
Toast.makeText(MainActivity.this, "ID:"+positionId, Toast.LENGTH_LONG).show();

}
});
}
private void extracted() {
showResult.setText("没有有效的数据!");
}
//和服务器连接
private String getContent(String url)throws Exception{
StringBuilder sb = new StringBuilder();
HttpClient client =new DefaultHttpClient();
HttpParams httpParams =client.getParams();

HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
HttpConnectionParams.setSoTimeout(httpParams, 5000);
HttpResponse response = client.execute(new HttpGet(url));
HttpEntity entity =response.getEntity();

if(entity !=null){
BufferedReader reader = new BufferedReader(new InputStreamReader
(entity.getContent(),"UTF-8"),8192);
String line =null;
while ((line= reader.readLine())!=null){
sb.append(line +"\n");
}
reader.close();
}
return sb.toString();
}

 

HttpURLConnection 类是一种重要的访问 HTTP 资源的方式。HttpURLConnection 类具有完全的访问能力,可以取代HttpGet和HttpPost类。使用HttpUrlConnection 访问HTTP资源可以使用如
下几步:

1.使用java.net.URL封装HTTP资源的url,并使用openConnection方法获得HttpUrlConnection 对象,代码如下:

URL url = new URL("http://www.blogjava.net/nokiaguy/archive/2009/12/14/305890.html");

HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();

2.设置请求方法,例如GET、POST等,代码如下:

httpURLConnection.setRequestMethod("POST");

要注意的是,setRequestMethod方法的参数值必须大写,例如GET、POST等。

3.设置输入输出及其他权限。如果要下载 HTTP资源或向服务端上传数据,需要使用如下代码进行设置:

// 下载 HTTP资源,需要将setDoInput方法的参数值设为true
httpURLConnection.setDoInput(true);
//
上传数据,需要将setDoOutput方法的参数值设为true
httpURLConnection.setDoOutput(true);

HttpURLConnection 类还包含更多的选项,例如,使用下面的代码可以禁止HttpURLConnection使用缓存。

httpURLConnection.setUseCaches(false);

4.设置HTTP请求头。在很多情况下,要根据实际情况设置一些HTTP请求头,例如下面的代码设置了Charset请求头的值为UTF-8。

httpURLConnection.setRequestProperty("Charset", "UTF-8");

5.输入和输出数据。这一步是对 HTTP 资源的读写操作,也就是通过 InputStream 和OutputStream读取和写入数据。下面的代码获得了InputStream对象和OutputStream对象。

InputStream is = httpURLConnection.getInputStream();
OutputStream os = httpURLConnection.getOutputStream();

至于是先读取还是先写入数据,需要根据具体情况而定。

6.关闭输入输出流。虽然关闭输入输出流并不是必需的,在应用程序结束后,输入输出流会自动关闭,但显式关闭输入输出流是一个好习惯。关闭输入输出流的代码如下:

is.close();
os.close();

 

转http://www.eoeandroid.com/thread-314728-1-1.html

最近在研究Volley框架的源码,发现它在HTTP请求的使用上比较有意思,在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。我也比较好奇这么使用的原因,于是专门找到了一位Google的工程师写的一篇博客,文中对 HttpURLConnection和HttpClient进行了对比,下面我就给大家简要地翻译一下。
原文地址:http://android-developers.blogspot.com/2011/09/androids-http-clients.html
大多数的Android应用程序都会使用HTTP协议来发送和接收网络数据,而Android中主要提供了两种方式来进行HTTP操 作,HttpURLConnection和HttpClient。这两种方式都支持HTTPS协议、以流的形式进行上传和下载、配置超时时间、IPv6、 以及连接池等功能。
HttpClientDefaultHttpClient和它的兄弟AndroidHttpClient都是HttpClient具体的实现类,它们都拥有众多的API,而且实现比较稳定,bug数量也很少。
但同时也由于HttpClient的API数量过多,使得我们很难在不破坏兼容性的情况下对它进行升级和扩展,所以目前Android团队在提升和优化HttpClient方面的工作态度并不积极。
HttpURLConnectionHttpURLConnection是一种多用途、轻量极的HTTP客户端,使用它来进行HTTP操作可以适用于大多数的应用程序。虽然HttpURLConnection的API提供的比较简单,但是同时这也使得我们可以更加容易地去使用和扩展它。
不过在Android 2.2版本之前,HttpURLConnection一直存在着一些令人厌烦的bug。比如说对一个可读的InputStream调用close()方法时,就有可能会导致连接池失效了。那么我们通常的解决办法就是直接禁用掉连接池的功能:
[java] view plaincopy

  • private void disableConnectionReuseIfNecessary() {  
  •     // 这是一个2.2版本之前的bug  
  •     if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {  
  •         System.setProperty("http.keepAlive", "false");  
  •     }  
  • }  


在Android 2.3版本的时候,我们加入了更加透明化的响应压缩。HttpURLConnection会自动在每个发出的请求中加入如下消息头,并处理相应的返回结果:Accept-Encoding: gzip

配置你的Web服务器来支持对客户端的响应进行压缩的功能,从而可以在这一改进上获取到最大的好处。如果在压缩响应的时候出现了问题,这篇文档会告诉你如何禁用掉这个功能。
但是如果启动了响应压缩的功能,HTTP响应头里的Content-Length就会代表着压缩后的长度,这时再使用 getContentLength()方法来取出解压后的数据就是错误的了。正确的做法应该是一直调用InputStream.read()方法来读取响 应数据,一直到出现-1为止。
我们在Android 2.3版本中还增加了一些HTTPS方面的改进,现在HttpsURLConnection会使用SNI(Server Name Indication)的方式进行连接,使得多个HTTPS主机可以共享同一个IP地址。除此之外,还增加了一些压缩和会话的机制。如果连接失败,它会自 动去尝试重新进行连接。这使得HttpsURLConnection可以在不破坏老版本兼容性的前提下,更加高效地连接最新的服务器。
在Android 4.0版本中,我们又添加了一些响应的缓存机制。当缓存被安装后(调用HttpResponseCache的install()方法),所有的HTTP请求都会满足以下三种情况:
所有的缓存响应都由本地存储来提供。因为没有必要去发起任务的网络连接请求,所有的响应都可以立刻获取到。
视情况而定的缓存响应必须要有服务器来进行更新检查。比如说客户端发起了一条类似于 “如果/foo.png这张图片发生了改变,就将它发送给我” 这样的请求,服务器需要将更新后的数据进行返回,或者返回一个304 Not Modified状态。如果请求的内容没有发生,客户端就不会下载任何数据。
没有缓存的响应都是由服务器直接提供的。这部分响应会在稍后存储到响应缓存中。
由于这个功能是在4.0之后的版本才有的,通常我们就可以使用反射的方式来启动响应缓存功能。下面的示例代码展示了如何在Android 4.0及以后的版本中去启用响应缓存的功能,同时还不会影响到之前的版本:
[java] view plaincopy

  • private void enableHttpResponseCache() {  
  •     try {  
  •         long httpCacheSize = 10 * 1024 * 1024; // 10 MiB  
  •         File httpCacheDir = new File(getCacheDir(), "http");  
  •         Class.forName("android.net.http.HttpResponseCache")  
  •             .getMethod("install", File.class, long.class)  
  •             .invoke(null, httpCacheDir, httpCacheSize);  
  •     } catch (Exception httpResponseCacheNotAvailable) {  
  •     }  
  • }  


你也应该同时配置一下你的Web服务器,在HTTP响应上加入缓存的消息头。哪一种才是最好的?在Android 2.2版本之前,HttpClient拥有较少的bug,因此使用它是最好的选择。
而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择。它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可 以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。对于新的应用程序应该更加偏向于使用HttpURLConnection,因为在 以后的工作当中我们也会将更多的时间放在优化HttpURLConnection上面。

 

客户端Socket连接服务器与服务器交互的代码如下

Socket socket = new Socket("192.168.17.100", 8080);    或者 Socket socket = new Socket(); socket.connect(new InetSocketAddress("192.168.18.100", 8080));


OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os)
BufferedWriter bw = new BufferedWriter(osw);

 

// 向服务器写数据
bw.write("hello world\r\n\r\n");
bw.flush();

InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String s = "";
//
从服务器读数据
while((s = br.readLine()) != null)
  Log.d("line", s);


//
下面的代码关闭输入输出流以及Socket连接
os.close();
is.close();
socket.close();

 

服务端Socket:

ServerSocket serverSocket = new ServerSocket(1234); // ServerSocket serverSocket = new ServerSocket(1234, 100);  100为请求队列的长度

// 处理其他任务的代码
while(true)
{
  Socket socket = serverSocket.accept(); //
等待接收客户端请求
  //
处理其他任务的代码
  new ThreadClass(socket).start(); //
创建并运行处理客户端请求的线程
}

 

 

 

上传文件的HTTP请求信息分为如下4部分:

1. 分界符。由两部分组成:两个连字符“--”和一个任意字符串。使用浏览器上传文件一般为“-----------------数字”。分界符为单独一行。

2. 上传文件的相关信息。这些信息包括请求参数名、上传文件名、文件类型,但并不仅限于此,例如Content-Disposition: form-data; name="file"; filename="abc.jpg"。

3. 上传文件的内容。字节流形式。

4. 文件全部上传后的结束符。这个符号在图中并没有显示出来。当上传的文件是最后一个时,在 HTTP请求信息的结尾就会出现这个符号字符串。结束符和分界符类似,只是在分界符后面再加两个连字符,例如,“-----------------------------------218813199810322--”就是一个结束符。

 

Android SDK支持访问HTTPS资源,代码如下:

 

// 信任所有的host
HostnameVerifier hostnameVerifier =
org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));

//
像访问HTTP资源一样使用httpClient 和 httpPost
DefaultHttpClient client = new DefaultHttpClient();
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
HttpPost httpPost = new HttpPost("https://www.myhttps.com");

// 下面的代码和访问HTTP资源完全一样

...

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2014-06-17 13:36  【雨歌】  阅读(1763)  评论(0)    收藏  举报