面試篇--android下網路通訊機制(三種網路通訊方式)
阿新 • • 發佈:2019-02-08
HttpClient
HttpClient是Apache對java中的HttpURLClient介面的封裝,主要引用org.apache.http.**。Google在2.3版本之前推薦使用HttpClient,因為這個封裝包安全性高,bug較少。
使用方法:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
public class HttpClientUtils {
private static HttpClient httpClient;
private static HttpClientUtils instance = null;
public static synchronized HttpClientUtils getInstance() {
if (instance == null) {
instance = new HttpClientUtils();
}
return instance;
}
private HttpClientUtils() {
// 學習volley請求佇列,HttpClient使用單例模式
if (httpClient == null) {
httpClient = new DefaultHttpClient();
}
}
/**
* 以get方式傳送請求,訪問介面
* @param uri連結地址
* @return 響應資料
*/
private static String doHttpGet(String uri) {
BufferedReader reader = null;
StringBuffer sb = null;
String result = "";
HttpGet request = new HttpGet(uri);
try {
// 傳送請求,得到響應
HttpResponse response = httpClient.execute(request);
// 請求成功,statuscode返回200
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
sb = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != reader) {
reader.close();
reader = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != sb) {
result = sb.toString();
}
return result;
}
/**
* 以post方式傳送請求,訪問介面
* @param uri連結地址
* @return 響應資料
*/
private static String doHttpPost(String uri) {
BufferedReader reader = null;
StringBuffer sb = null;
String result = "";
HttpPost request = new HttpPost(uri);
// 儲存要傳遞的引數
List<NameValuePair> params = new ArrayList<NameValuePair>();
// 新增引數
params.add(new BasicNameValuePair("parameter", "以Post方式傳送請求"));
try {
// 設定字符集
HttpEntity entity = new UrlEncodedFormEntity(params, "utf-8");
// 請求物件
request.setEntity(entity);
// 傳送請求
HttpResponse response = httpClient.execute(request);
// 請求成功
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
System.out.println("post success");
reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
sb = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 關閉流
if (null != reader) {
reader.close();
reader = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != sb) {
result = sb.toString();
}
return result;
}
}
HttpURLConnection
HttpURLConnection在java.NET下,繼承自URLConnection類,相對於HttpClient具有擴充套件性高、靈活性高,更輕量級的優點,所以Google在2.3版本之後推薦大家使用HttpURLConnection來操作網路請求。
使用方法:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class HttpURLConnectUtils {
private static HttpURLConnectUtils instance = null;
public static synchronized HttpURLConnectUtils getInstance() {
if (instance == null) {
instance = new HttpURLConnectUtils();
}
return instance;
}
private HttpURLConnectUtils() {
}
// post
public String dohttppost(String mUrl) throws IOException {
URL url = new URL(mUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();//初始化建立HttpURLConnection例項
httpURLConnection.setConnectTimeout(5000);//推薦設定網路延時
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setUseCaches(false);
httpURLConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");
httpURLConnection.setRequestMethod("POST");
//設定引數
OutputStream outputStream = httpURLConnection.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
String params = new String();//這裡簡單設定引數
params = "name=" + URLEncoder.encode("高冉", "GBK");
objectOutputStream.writeBytes(params);
objectOutputStream.flush();
objectOutputStream.close();
//接收返回值
//String msg = httpURLConnection.getResponseMessage();// 接收簡單string
InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder builder = new StringBuilder();
for (String s = bufferedReader.readLine(); s != null; s = bufferedReader.readLine()) {
builder.append(s);
}
return builder.toString();
}
// get
public String dohttpget(String mUrl) throws IOException {
URL url = new URL(mUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(5000);//推薦設定網路延時
httpURLConnection.setRequestMethod("GET");
httpURLConnection.connect();
// String msg = httpURLConnection.getResponseMessage();
InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder builder = new StringBuilder();
for (String s = bufferedReader.readLine(); s != null; s = bufferedReader.readLine()) {
builder.append(s);
}
return builder.toString();
}
}
還需要注意一些細節:
1、post與get區別在於post將引數置於請求資料中,get則跟在url連結後面。
2、大檔案下載操作要置於sd卡中,不要放在手機記憶體中操作,而且需要邊讀邊寫,不要使用Buffered做快取。
三、我們看一個簡單的socket程式設計,實現伺服器回發客戶端資訊。
下面用個例子來說明:
A、客戶端:
新建Android專案工程:SocketForAndroid(這個隨意起名字了吧,我是以這個建立的!)
下面是main_activity.xml的程式碼:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?xml version= "1.0" encoding= "utf-8" ?>
android:layout_width= "fill_parent"
android:layout_height= "fill_parent"
android:orientation= "vertical" >
<TextView
android:layout_width= "fill_parent"
android:layout_height= "wrap_content"
android:text= "@string/hello" />
<EditText
android:id= "@+id/message"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:hint= "@string/hint" />
<Button
android:id= "@+id/send"
android:layout_width= "fill_parent"
android:layout_height= "wrap_content"
android:text= "@string/send" />
</LinearLayout>
|
MainActivity.java的程式碼入下:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
package
com.yaowen.socketforandroid;
import
android.os.Bundle;
import
android.support.v7.app.AppCompatActivity;
import
android.view.View;
import
android.widget.Button;
import
android.widget.EditText;
import
java.io.BufferedReader;
import
java.io.BufferedWriter;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.io.OutputStreamWriter;
import
java.io.PrintWriter;
import
java.net.Socket;
public
class MainActivity extends AppCompatActivity {
private EditText message;
private Button send;
@Override
protected void
onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化兩個UI控制元件
message = (EditText) findViewById(R.id.message);
send = (Button) findViewById(R.id.send);
//設定傳送按鈕的點選事件響應
send.setOnClickListener( new View.OnClickListener() {
@Override
public void
onClick(View v) {
Socket socket = null ;
//獲取message輸入框裡的輸入的內容
String msg = message.getText().toString() + "\r\n" ;
try {
//這裡必須是192.168.3.200,不可以是localhost或者127.0.0.1
socket = new
Socket( "192.168.3.200" , 18888 );
PrintWriter out = new
PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream()
)
), true );
//傳送訊息
out.println(msg);
//接收資料
BufferedReader in = new
BufferedReader(
new InputStreamReader(
socket.getInputStream()
)
);
//讀取接收的資料
String msg_in = in.readLine();
if ( null
!= msg_in) {
message.setText(msg_in);
System.out.println(msg_in);
} else
{
message.setText( "接收的資料有誤!" );
}
//關閉各種流
out.close();
in.close();
} catch
(IOException e) {
e.printStackTrace();
} finally
{
try {
if ( null
!= socket) {
//socket不為空時,最後記得要把socket關閉
socket.close();
}
} catch
(IOException e) {
e.printStackTrace();
}
}
}
});
}
}
|
最後別忘記新增訪問網路許可權:
<uses-permission android:name="android.permission.INTERNET" />
B、服務端:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
package
service;
import
java.io.BufferedReader;
import
java.io.BufferedWriter;
import
java.io.IOException;
import
java.io.InputStreamReader;
import
java.io.OutputStreamWriter;
import
java.io.PrintWriter;
import
java.net.ServerSocket;
import
java.net.Socket;
public
class ServerAndroid implements Runnable {
@Override
public void
run() {
Socket socket = null ;
try {
ServerSocket server = new
ServerSocket( 18888 );
// 迴圈監聽客戶端連結請求
while ( true ) {
System.out.println( "start..." );
// 接收請求
socket = server.accept();
System.out.println( "accept..." );
// 接收客戶端訊息
BufferedReader in = new
BufferedReader( new InputStreamReader(socket.getInputStream()));
String message = in.readLine();
System.out.println(message);
// 傳送訊息,向客戶端
PrintWriter out = new
PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),
true );
out.println( "Server:" + message);
// 關閉流
in.close();
out.close();
}
} catch
(IOException e) {
e.printStackTrace();
} finally
{
if ( null
!= socket) {
try {
socket.close();
} catch
(IOException e) {
e.printStackTrace();
}
}
}
}
// 啟動伺服器
public static
void main(String[] args) {
Thread server = new
Thread( new ServerAndroid());
server.start();
}
}
|
C、啟動伺服器,控制檯會打印出“start...”字串!
D、執行Android專案檔案,如下圖:
在輸入框裡輸入如下字串,點發送按鈕:
伺服器收到客戶端發來的訊息並列印到控制檯: