Android Socket通信
- 什么是Socket
是一種抽象層,簡單來說,Socket提供了程序內(nèi)部與外界通訊的端口,并為雙方提供了數(shù)據(jù)傳輸通道。 - Socket分類
根據(jù)不同的底層協(xié)議,Socket的實現(xiàn)是多樣化的。我了解的是基于TCP/IP協(xié)議族,在這個協(xié)議族中主要的Socket類型為流套接字和數(shù)據(jù)套接字。流套接字將TCP作為其端對端協(xié)議,提供了一個值得信賴的字節(jié)流服務(wù)。數(shù)據(jù)報套接字使用UDP協(xié)議,提供數(shù)據(jù)打包發(fā)送服務(wù)。 - Socket基本實現(xiàn)原理
服務(wù)端首先聲明一個Serversocket對象并且指定其端口號,然后調(diào)用accept()方法接受客戶端數(shù)據(jù)。accept()方法在沒接收到數(shù)據(jù)處于堵塞狀態(tài),一旦接受到數(shù)據(jù),通過inputstream讀取接受數(shù)據(jù)。
客戶端創(chuàng)建一個Socket對象,指定服務(wù)器端IP和端口號
Socket socket=new Socket(“127.0.0.1”,8080);
通過inputstream讀取數(shù)據(jù),獲取服務(wù)器發(fā)出的數(shù)據(jù)
OutputStream os=socket.getOutputStream();
通過OutputStream發(fā)送數(shù)據(jù)
進行TCP協(xié)議Socket數(shù)據(jù)傳輸
- 一般步驟
1.打開連接
2.取得outputstream和inputstream
3.關(guān)閉連接
package com.example.sgcchj;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class ScoketUtils {
private static Socket socket;
private static InputStream is;
private static InputStreamReader isr;
private static BufferedReader br;
private static OutputStream outputStream;
public static void openlink(){
try {
// 創(chuàng)建Socket對象 & 指定服務(wù)端的IP 及 端口號
socket = new Socket("192.168.0.102", 10086);
// 判斷客戶端和服務(wù)器是否連接成功
System.out.println(socket.isConnected()+"是否連接成功");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void readlink(){
try {
is = socket.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String response = br.readLine();
System.out.println(response+"這是個啥");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writelink(String data){
try {
outputStream = socket.getOutputStream();
byte[] b=data.getBytes("utf-8");
outputStream.write(b);
outputStream.flush();
} catch (IOException e) {
}
}
public static void closelink(){
try {
if(outputStream!=null){
outputStream.close();
}
if(br!=null){
br.close();
}
if(socket!=null){
socket.close();
System.out.println(socket.isConnected());
}
} catch (IOException e) {
}
}
}
Android HTTP通信
- 什么是HTTP協(xié)議
HTTP協(xié)議即超文本傳送協(xié)議(Hypertext Transfer Protocol ),是Web聯(lián)網(wǎng)的基礎(chǔ),也是手機聯(lián)網(wǎng)常用的協(xié)議之一,HTTP協(xié)議是建立在TCP協(xié)議之上的一種應(yīng)用。
HTTP連接最顯著的特點是客戶端發(fā)送的每次請求都需要服務(wù)器回送響應(yīng),在請求結(jié)束后,會主動釋放連接。從建立連接到關(guān)閉連接的過程稱為“一次連接”。
HTTP是一個屬于應(yīng)用層的面向?qū)ο蟮膮f(xié)議,Http協(xié)議基于傳輸層的TCP協(xié)議,主要解決如何包裝數(shù)據(jù) - Android開發(fā)調(diào)用
Android中提供的HttpURLConnection和HttpClient(已過時,不在說)和開源的okhttp3接口可以用來開發(fā)HTTP程序。
1. HttpURLConnection接口
首先需要明確的是,Http通信中的POST和GET請求方式的不同。GET可以獲得靜態(tài)頁面,也可以把參數(shù)放在URL字符串后面,傳遞給服務(wù)器。而POST方法的參數(shù)是放在Http請求中。因此,在編程之前,應(yīng)當(dāng)首先明確使用的請求方法,然后再根據(jù)所使用的方式選擇相應(yīng)的編程方式。
HttpURLConnection是繼承于URLConnection類,二者都是抽象類。其對象主要通過URL的openConnection方法獲得。創(chuàng)建方法如下代碼所示:
URL url = new URL("http://127.0.0.1/post.jsp");
HttpURLConnection urlConn=(HttpURLConnection)url.openConnection();
通過以下方法可以對請求的屬性進行一些設(shè)置,如下所示
//設(shè)置輸入和輸出流
urlConn.setDoOutput(true);
urlConn.setDoInput(true);
//設(shè)置請求方式為POST
urlConn.setRequestMethod("POST");
//POST請求不能使用緩存
urlConn.setUseCaches(false);
//關(guān)閉連接
urlConn.disConnection();
Manifest文件中權(quán)限的設(shè)定:
Xml代碼
<uses-permission android:name="android.permission.INTERNET" />
HttpURLConnection默認(rèn)使用GET方式,例如下面代碼所示:
//以Get方式上傳參數(shù)
public class Activity1 extends Activity
{
private final String DEBUG_TAG = "Activity1";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.http);
TextView mTextView = (TextView)this.findViewById(R.id.tv_http);
//http地址"?id=1"是我們上傳的參數(shù)
String httpUrl = "http://127.0.01:8080/index.jsp?id=1";
//獲得的數(shù)據(jù)
String resultData = "";
URL url = null;
try
{
//構(gòu)造一個URL對象
url = new URL(httpUrl);
}
catch (MalformedURLException e)
{
Log.e(DEBUG_TAG, "完犢子");
}
if (url != null)
{
try
{
// 使用HttpURLConnection打開連接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//得到讀取的內(nèi)容(流)
InputStreamReader in = new InputStreamReader(urlConn.getInputStream());
// 為輸出創(chuàng)建BufferedReader
BufferedReader buffer = new BufferedReader(in);
String Line = null;
//使用循環(huán)來讀取獲得的數(shù)據(jù)
while (((Line = buffer.readLine()) != null))
{
//我們在每一行后面加上一個"\n"來換行
resultData += Line + "\n";
}
//關(guān)閉InputStreamReader
in.close();
//關(guān)閉http連接
urlConn.disconnect();
//設(shè)置顯示取得的內(nèi)容
if ( resultData != null )
{
mTextView.setText(resultData);
}
else
{
mTextView.setText("讀取的內(nèi)容為NULL");
}
}
catch (IOException e)
{
Log.e(DEBUG_TAG, "扯犢子");
}
}
else
{
Log.e(DEBUG_TAG, "Url NULL");
}
}
如果需要使用POST方式,則需要setRequestMethod設(shè)置。代碼如下:
//以post方式上傳參數(shù)
public class Activity2extends Activity
{
private final String DEBUG_TAG = "Activity2";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.http);
TextView mTextView = (TextView)this.findViewById(R.id.TextView_HTTP);
//http地址"?id=1"是我們上傳的參數(shù)
String httpUrl = "http://192.168.1.110:8080/post.jsp";
//獲得的數(shù)據(jù)
String resultData = "";
URL url = null;
try
{
//構(gòu)造一個URL對象
url = new URL(httpUrl);
}
catch (MalformedURLException e)
{
Log.e(DEBUG_TAG, "MalformedURLException");
}
if (url != null)
{
try
{
// 使用HttpURLConnection打開連接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//因為這個是post請求,設(shè)立需要設(shè)置為true
urlConn.setDoOutput(true);
urlConn.setDoInput(true);
// 設(shè)置以POST方式
urlConn.setRequestMethod("POST");
// Post 請求不能使用緩存
urlConn.setUseCaches(false);
urlConn.setInstanceFollowRedirects(true);
// 配置本次連接的Content-type,配置為application/x-www-form-urlencoded的
urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
// 連接,從postUrl.openConnection()至此的配置必須要在connect之前完成,
// 要注意的是connection.getOutputStream會隱含的進行connect。
urlConn.connect();
//DataOutputStream流
DataOutputStream out = new DataOutputStream(urlConn.getOutputStream());
//要上傳的參數(shù)
String content = "par=" + URLEncoder.encode("ABCDEFG", "gb2312");
//將要上傳的內(nèi)容寫入流中
out.writeBytes(content);
//刷新、關(guān)閉
out.flush();
out.close();
//獲取數(shù)據(jù)
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
String inputLine = null;
//使用循環(huán)來讀取獲得的數(shù)據(jù)
while (((inputLine = reader.readLine()) != null))
{
//我們在每一行后面加上一個"\n"來換行
resultData += inputLine + "\n";
}
reader.close();
//關(guān)閉http連接
urlConn.disconnect();
//設(shè)置顯示取得的內(nèi)容
if ( resultData != null )
{
mTextView.setText(resultData);
}
else
{
mTextView.setText("讀取的內(nèi)容為NULL");
}
}
catch (IOException e)
{
Log.e(DEBUG_TAG, "IOException");
}
}
else
{
Log.e(DEBUG_TAG, "Url NULL");
}
}
}
2.okhttp3接口
導(dǎo)入:compile 'com.squareup.okhttp3:okhttp:3.9.0'
Get請求
String url = "https://127.0.0.1/";
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Call call = okHttpClient.newCall(request);
try {
Response response = call.execute();
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
傳參:
Request request = new Request.Builder()
.url(url)
.header(key, value)
.build();
Post請求
String url = "https://127.0.0.1";
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody body = new FormBody.Builder()
.add(key, value)
.build();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Call call = okHttpClient.newCall(request);
try {
Response response = call.execute();
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
post請求創(chuàng)建request和get是一樣的,post請求需要提交一個表單,就是RequestBody。
RequestBody body = new FormBody.Builder()
.add(key, value)
.build();