Android中Socket通訊的簡單實現
前言
Android Framework 層程式碼中大量使用了 Binder IPC 通訊方式,除此之外,Socket 也是一種重要的 IPC 通訊方式,比如StorageManagerService(8.0 之前叫 MountService)與 Vold 之前的通訊,SystemServer 和 Zygote 之間也是通過 Socket 進行通訊的。
本文簡單總結下 Android Java 層在使用 Socket 通訊時的一般步驟,然後給出一個簡單的 demo。
原理性的東西涉及到不同網路層之間的協議,本著簡單、實用、粗暴的原則,本文暫不涉及原理性的東西。
上圖是從 https://blog.csdn.net/yhaolpz/article/details/59483916 處扒來的圖片,以下例項程式碼也是從該處獲取,非原創。
1,Socket通訊的實現步驟
Socket 通訊和 Binder 通訊類似,也是一種 C/S 模型的通訊方式。
1.1 Server 服務端
步驟一: 建立一個伺服器 Socket
常見的一個伺服器 Socket 類是 ServerSocket,ServerSocket 類常用三個方法:binder 、accept、close。
bind 方法為 ServerSocket 繫結 IP 地址和埠號,並開始監聽該埠;accept 方法為 ServerSocket 接收請求並返回一個Socket 物件,accept 方法呼叫之後將一直阻塞,直到有請求達到;close 方法關閉一個 ServerSocket 物件。
初始化是一般需要設定 IP 地址和埠號
步驟二: 通過監聽獲取一個用於通訊的 Socket 物件
這一步直接通過上述 accept 方法的執行就可實現
步驟三: 在一個新執行緒中,通過對 Socket 物件進行封裝,分別得到輸入、輸出流的引用物件,通過這兩個物件向 Client 端傳送或者從 Client 端接收資料,進而實現 Socket 通訊。
一般選擇在迴圈中讀取 Client 傳送過來的資訊,並作出對應的處理,比如反饋 Client 端:自己已成功收到相應的訊息。
步驟四: 在適當的時機關閉 Socket 連線
服務端程式碼:
public class SocketTest {
private static final int PORT = 9999;
private List<Socket> mList = new ArrayList<Socket>();
private ServerSocket server = null;
private ExecutorService mExecutorService = null;
private String receiveMsg;
private String sendMsg;
public static void main(String[] args) {
new SocketTest();
}
public SocketTest() {
try {
server = new ServerSocket(PORT); //步驟一
mExecutorService = Executors.newCachedThreadPool();
System.out.println("伺服器已啟動...");
Socket client = null;
while (true) {
client = server.accept(); //步驟二,每接受到一個新Socket連線請求,就會新建一個Thread去處理與其之間的通訊
mList.add(client);
mExecutorService.execute(new Service(client));
}
} catch (Exception e) {
e.printStackTrace();
}
}
class Service implements Runnable {
private Socket socket;
private BufferedReader in = null;
private PrintWriter printWriter=null;
public Service(Socket socket) { //這段程式碼對應步驟三
this.socket = socket;
try {
printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter( socket.getOutputStream(), "UTF-8")), true);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream(),"UTF-8"));
printWriter.println("成功連線伺服器"+"(伺服器傳送)");
System.out.println("成功連線伺服器");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
while (true) { //迴圈接收、讀取 Client 端傳送過來的資訊
if ((receiveMsg = in.readLine())!=null) {
System.out.println("receiveMsg:"+receiveMsg);
if (receiveMsg.equals("0")) {
System.out.println("客戶端請求斷開連線");
printWriter.println("服務端斷開連線"+"(伺服器傳送)");
mList.remove(socket);
in.close();
socket.close(); //接受 Client 端的斷開連線請求,並關閉 Socket 連線
break;
} else {
sendMsg = "我已接收:" + receiveMsg + "(伺服器傳送)";
printWriter.println(sendMsg); //向 Client 端反饋、傳送資訊
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
1.2 Client 客戶端
步驟一: 初始化 Socket 物件
客戶端一般選擇在一個新的執行緒中,初始化一個 Socket 物件,初始化是需要設定 IP 和埠號,以幫助低層網路路由找到相應的服務端程序。
步驟二: 獲取與 Server 端通訊的引用
此步和 Server 端建立連線後的步驟類似:根據步驟一中獲取的 Socket 物件,進行封裝,得到相應的輸入、輸出流物件,這些輸入、輸出流物件就是和 Server 端進行通訊的引用。
步驟三: 通過步驟二中得到的引用,迴圈的讀取(在新執行緒中) Server 端傳送過來的訊息,並做相應的處理
步驟四:在合適的時機關閉與 Server 端的 Socket 連線
參考以下客戶端程式碼:
public class SocketActivity extends AppCompatActivity {
private EditText mEditText;
private TextView mTextView;
private static final String TAG = "TAG";
private static final String HOST = "192.168.23.1";
private static final int PORT = 9999;
private PrintWriter printWriter;
private BufferedReader in;
private ExecutorService mExecutorService = null;
private String receiveMsg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_socket);
mEditText = (EditText) findViewById(R.id.editText);
mTextView = (TextView) findViewById(R.id.textView);
mExecutorService = Executors.newCachedThreadPool();
}
public void connect(View view) {
mExecutorService.execute(new connectService()); //在一個新的執行緒中請求 Socket 連線
}
public void send(View view) {
String sendMsg = mEditText.getText().toString();
mExecutorService.execute(new sendService(sendMsg));
}
public void disconnect(View view) {
mExecutorService.execute(new sendService("0"));
}
private class sendService implements Runnable {
private String msg;
sendService(String msg) {
this.msg = msg;
}
@Override
public void run() {
printWriter.println(this.msg);
}
}
private class connectService implements Runnable {
@Override
public void run() {//可以考慮在此處新增一個while迴圈,結合下面的catch語句,實現Socket物件獲取失敗後的超時重連,直到成功建立Socket連線
try {
Socket socket = new Socket(HOST, PORT); //步驟一
socket.setSoTimeout(60000);
printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter( //步驟二
socket.getOutputStream(), "UTF-8")), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
receiveMsg();
} catch (Exception e) {
Log.e(TAG, ("connectService:" + e.getMessage())); //如果Socket物件獲取失敗,即連線建立失敗,會走到這段邏輯
}
}
}
private void receiveMsg() {
try {
while (true) { //步驟三
if ((receiveMsg = in.readLine()) != null) {
Log.d(TAG, "receiveMsg:" + receiveMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(receiveMsg + "\n\n" + mTextView.getText());
}
});
}
}
} catch (IOException e) {
Log.e(TAG, "receiveMsg: ");
e.printStackTrace();
}
}
}
2. 總結
原諒我這篇文章結構上的簡潔和草率,哈哈,第二部分就直接結束了
在實現Socket通訊時要重點關注新執行緒和while迴圈的使用。
在Android主執行緒中不能進行網路通訊的大原則下,Server端和Client端分別使用不同的機制,在新執行緒中啟動Socket連線;連線建立之後,通過while迴圈實現通訊雙方的“準實時”訊息處理。
相關推薦
Android中Socket通訊的簡單實現
前言Android Framework 層程式碼中大量使用了 Binder IPC 通訊方式,除此之外,Socket 也是一種重要的 IPC 通訊方式,比如StorageManagerService(8.0 之前叫 MountService)與 Vold 之前的通訊,Syst
Android中MQTT的簡單實現(只是連線到伺服器,未實現傳送、接受資訊)
1.新增mqtt包到gradle.build a.在project的gradle.build中新增地址(P:我下載的參考例子是不用新增的,但是我自己寫的時候不新增就編譯不過去) allprojects { repositories { google()
Android中Https通訊實現_ 單向認證
客戶端與服務端單向認證即是在客戶端的網路請求和webview中設定信任所有證書,然後在與服務端進行Https網路通訊的時候,客戶端不必進行證書校驗也能進行網路通訊,否則就會報證書不受信異常。 缺陷:容易受到中間人攻擊。 概覽 TrustManager和Hos
Android中Https通訊實現_瞭解Https
概覽 什麼是Https Https和Http的區別 Https證書 什麼是Https HTTPS(全稱:Hypertext Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP通道,簡單講是
Android中通過ListView的實現簡單新聞列表
Android中實現簡單的新聞列表 “本文主要針對Android新手,大神請繞道…” 使用到的第三方庫 Retrofit2+RxJava2 進行網路請和json資料的解析,註解框架:Butterknife 8.5.1 如果以上的框架還有同學不知道怎麼使用可以看看
Android中Https通訊實現_中間人攻擊、DNS欺騙和會話劫持
上一篇文章記述了在Android中使用Https進行單向認證的配置,但單向認證存在中嚴重的安全漏洞,其中最容易受到中間人攻擊和DNS欺騙以及會話劫持,本文主要講述進行中間人攻擊、DNS欺騙和會話劫持的方式。 概覽 什麼是中間人攻擊 模擬中間人攻擊
C#中Socket通訊程式設計的非同步實現
本文將在C#中Socket同步通訊的基礎上,分析和研究Socket非同步程式設計的實現方法,目的是深入瞭解Socket程式設計的基本原理,增強對網路遊戲開發相關內容的認識。 什麼是Socket程式設計的非同步是實現 所謂Socket程式設計的非同步實現是指按
android中ping命令的實現
ack ces buffered amr 實現 int time() ade article /** * 推斷Ping 網址是否返回成功 * * @param netAddress * @return */ public static String isPingSuc
Android中Socket大文件斷點上傳
lai 大於 兩個類 bundle use 分配 1.0 應該 subst 什麽是Socket? 所謂Socket通常也稱作“套接字”,用於描述IP地址和端口,是一個通信連的句柄,應用程序通常通過“套接字&rdquo
Android中AlertDialog的簡單使用
android中彈框很多種,alert框,dialog,AlertDialog,popupwindow,DialogFragment,toast,dialog樣式的activity等等,今天講解AlertDialog的簡單使用。 1 AlertDialog.Builder 設定相關引
android中定時器的實現學習
資料來自於 簡書 沿路旅程如歌蛻變 點這裡 利用handler.postDelay()方法來實現定時器計時 下面的程式碼實現了6s倒計時,計時後,自動停止計時並移除runnable. public class MainActivity extends AppCompat
Android中ListView的簡單使用
動態新增單行列表: 首先前提是你的佈局檔案裡有一個ListView 單行列表的新增只需要一個list集合即可,使用ArrayAdapter陣列介面卡繫結更新就行了 首先宣告一個ArrayAdapter物件: ArrayAdapter adapter adapter = new ArrayAdapter(
通過aspectj對Android資料統計的簡單實現
功能需求 一個專案實現之後,我們並不知道使用者對某個部分的使用頻率是對少,為了更好的來對專案各個功能的使用統計,我們需要做一些資料埋點的功能,也就是每當使用者點選按鈕的時候,都對這次點選進行儲存處理,然後再之後統一上傳到伺服器,進行資料分析。 實現思路 條件 假如,當前有
一文了解Android中路由(Router)的實現
Router 對於一個功能越來越複雜的APP來說,路由對於程式碼的解耦、頁面靈活跳轉配置、頁面攔截功能提供了很好的支援。下面我將分析業界比較出名的兩個路由框架WMRouter和ARouter的原始碼,瞭解他們的實現原理。 這兩個框架的實現核心原理是差不多的: 通過註解標註路由資訊,在編譯期動態掃描路由資訊
Android之Socket通訊
Android裡面使用Socket與伺服器之間進行通訊: 首先建立一個SocThread類 package com.junto.sockettest; import android.content.Context; import android.content.SharedPref
android中如何使用GPU實現硬體加速,3D渲染
已開通新的部落格,後續文字都會發到新部落格 http://www.0xfree.top --- 首先來看一些名詞解釋 GPU:Graphic Processing Unit (圖形處理器)&nb
android 呼叫手機打電話 簡單實現 ,
首先看下佈局xml ,我的事一個button按鈕 點選 打電話 ,手機號是自己定義,這個你可以根據自己邏輯寫 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas
Android轉盤抽獎的簡單實現
public class ZhuanPan2 extends View implements View.OnClickListener{ private Paint mPaint; private int mwidth; private int mpidding; p
Android中使用JiaoZiVideoPlayer來實現視訊列表播放的效果
目的:我這邊是想做類似於鬥魚直播裡的視訊模組的視訊列表播放形式。 然後下載程式碼,根據自己需要的樣式去找相應的程式碼進行研究。 效果圖如下: 使用步驟: (1)新增遠端依賴: /*呼叫Video視訊播放器*/ implementation 'cn.jzvd:
關於Java中Socket通訊時使用ObjectInputStream與ObjectOutputStream的順序問題
在Java中使用Socket與ServerSocket建立客戶機和伺服器時,若採用ObjectInputStream與ObjectOutputStream建立通訊,則需要注意兩個流的順序。否則會發生兩方互相等待導致死鎖。 下面通過一個例子來證明: 伺服器: package com.gar