摘要:簡介簡介也稱作套接字,是在應(yīng)用層和傳輸層之間的一個(gè)抽象層,它把層復(fù)雜的操作抽象為幾個(gè)簡單的接口供應(yīng)用層調(diào)用以實(shí)現(xiàn)進(jìn)程在網(wǎng)絡(luò)中通信。它分為流式套接字和數(shù)據(jù)包套接字,分別對(duì)應(yīng)網(wǎng)絡(luò)傳輸控制層的和協(xié)議。
Socket也稱作“套接字“,是在應(yīng)用層和傳輸層之間的一個(gè)抽象層,它把TCP/IP層復(fù)雜的操作抽象為幾個(gè)簡單的接口供應(yīng)用層調(diào)用以實(shí)現(xiàn)進(jìn)程在網(wǎng)絡(luò)中通信。它分為流式套接字和數(shù)據(jù)包套接字,分別對(duì)應(yīng)網(wǎng)絡(luò)傳輸控制層的TCP和UDP協(xié)議。TCP協(xié)議是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。它使用三次握手協(xié)議建立連接,并且提供了超時(shí)重傳機(jī)制,具有很高的穩(wěn)定性。UDP協(xié)議則是是一種無連接的協(xié)議,且不對(duì)傳送數(shù)據(jù)包進(jìn)行可靠性保證,適合于一次傳輸少量數(shù)據(jù),UDP傳輸?shù)目煽啃杂蓱?yīng)用層負(fù)責(zé)。在網(wǎng)絡(luò)質(zhì)量令人十分不滿意的環(huán)境下,UDP協(xié)議數(shù)據(jù)包丟失會(huì)比較嚴(yán)重。但是由于UDP的特性:它不屬于連接型協(xié)議,因而具有資源消耗小,處理速度快的優(yōu)點(diǎn),所以通常音頻、視頻和普通數(shù)據(jù)在傳送時(shí)使用UDP較多。?
從上圖我們也可以看出,不同的用戶進(jìn)程通過Socket來進(jìn)行通信,所以Socket也是一種IPC方式,接下來我們用TCP服務(wù)來實(shí)現(xiàn)一個(gè)簡單的聊天程序。
首先我們來實(shí)現(xiàn)服務(wù)端,當(dāng)然要使用Socket我們需要在AndroidManifest.xml聲明如下的權(quán)限:
我們需要實(shí)現(xiàn)一個(gè)遠(yuǎn)程的Service來當(dāng)作聊天程序的服務(wù)端,AndroidManifest.xml文件中配置service:
接下來我們?cè)赟ervice啟動(dòng)時(shí),在線程中建立TCP服務(wù),我們監(jiān)聽的是8688端口,等待客戶端連接,當(dāng)客戶端連接時(shí)就會(huì)生成Socket。通過每次創(chuàng)建的Socket就可以和不同的客戶端通信了。當(dāng)客戶端斷開連接時(shí),服務(wù)端也會(huì)關(guān)閉Socket并結(jié)束結(jié)束通話線程。服務(wù)端首先會(huì)向客戶端發(fā)送一條消息:“您好,我是服務(wù)端”,并接收客戶端發(fā)來的消息,將收到的消息進(jìn)行加工再返回給客戶端。
package com.example.liuwangshu.moonsocket; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; 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 SocketServerService extends Service { private boolean isServiceDestroyed = false; @Override public void onCreate() { new Thread(new TcpServer()).start(); super.onCreate(); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } private class TcpServer implements Runnable { @Override public void run() { ServerSocket serverSocket; try { //監(jiān)聽8688端口 serverSocket = new ServerSocket(8688); } catch (IOException e) { return; } while (!isServiceDestroyed) { try { // 接受客戶端請(qǐng)求,并且阻塞直到接收到消息 final Socket client = serverSocket.accept(); new Thread() { @Override public void run() { try { responseClient(client); } catch (IOException e) { e.printStackTrace(); } } }.start(); } catch (IOException e) { e.printStackTrace(); } } } } private void responseClient(Socket client) throws IOException { // 用于接收客戶端消息 BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); // 用于向客戶端發(fā)送消息 PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true); out.println("您好,我是服務(wù)端"); while (!isServiceDestroyed) { String str = in.readLine(); Log.i("moon", "收到客戶端發(fā)來的信息" + str); if (TextUtils.isEmpty(str)) { //客戶端斷開了連接 Log.i("moon", "客戶端斷開連接"); break; } String message = "收到了客戶端的信息為:" + str; // 從客戶端收到的消息加工再發(fā)送給客戶端 out.println(message); } out.close(); in.close(); client.close(); } @Override public void onDestroy() { isServiceDestroyed = true; super.onDestroy(); } }
客戶端Activity會(huì)在onCreate方法中啟動(dòng)服務(wù)端,并開啟線程連接服務(wù)端Socket。為了確保能連接成功,采用了超時(shí)重連的策略,每次連接失敗時(shí)都會(huì)重新建立連接。連接成功后,客戶端會(huì)收到服務(wù)端發(fā)送的消息:“您好,我是服務(wù)端”,我們也可以在EditText輸入字符并發(fā)送到服務(wù)端。
package com.example.liuwangshu.moonsocket; import android.content.Intent; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; 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 SocketClientActivity extends AppCompatActivity { private Button bt_send; private EditText et_receive; private Socket mClientSocket; private PrintWriter mPrintWriter; private TextView tv_message; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_socket); initView(); Intent service = new Intent(this, SocketServerService.class); startService(service); new Thread() { @Override public void run() { connectSocketServer(); } }.start(); } private void initView() { et_receive= (EditText) findViewById(R.id.et_receive); bt_send= (Button) findViewById(R.id.bt_send); tv_message= (TextView) this.findViewById(R.id.tv_message); bt_send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String msg = et_receive.getText().toString(); //向服務(wù)器發(fā)送信息 if(!TextUtils.isEmpty(msg)&&null!=mPrintWriter) { mPrintWriter.println(msg); tv_message.setText(tv_message.getText() + "n" + "客戶端:" + msg); et_receive.setText(""); } } }); } private void connectSocketServer() { Socket socket = null; while (socket == null) { try { //選擇和服務(wù)器相同的端口8688 socket = new Socket("localhost", 8688); mClientSocket = socket; mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); } catch (IOException e) { SystemClock.sleep(1000); } } try { // 接收服務(wù)器端的消息 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); while (!isFinishing()) { final String msg = br.readLine(); if (msg != null) { runOnUiThread(new Runnable() { @Override public void run() { tv_message.setText(tv_message.getText() + "n" + "服務(wù)端:" + msg); } } ); } } mPrintWriter.close(); br.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
布局很簡單(activity_socket.xml):
運(yùn)行程序,我們可以看到客戶端和服務(wù)端是兩個(gè)進(jìn)程:?
客戶端首先會(huì)收到服務(wù)端的信息:”您好,我是服務(wù)端”,接下來我們向服務(wù)端發(fā)送“我想要怒放的生命”。這時(shí)候服務(wù)端收到了這條信息并返回給客戶端加工后的這條信息:?
https://github.com/henrymorgen/MoonSocket
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/2026.html
摘要:中為何新增來作為主要的方式運(yùn)行機(jī)制是怎樣的機(jī)制有什么優(yōu)勢(shì)運(yùn)行機(jī)制是怎樣的基于通信模式,除了端和端,還有兩角色一起合作完成進(jìn)程間通信功能。 目錄介紹 2.0.0.1 什么是Binder?為什么要使用Binder?Binder中是如何進(jìn)行線程管理的?總結(jié)binder講的是什么? 2.0.0.2 Android中進(jìn)程和線程的關(guān)系?什么是IPC?為何需要進(jìn)行IPC?多進(jìn)程通信可能會(huì)出現(xiàn)什么問...
摘要:前言進(jìn)程間通信簡稱就是指進(jìn)程與進(jìn)程之間進(jìn)行通信一般來說一個(gè)只有一個(gè)進(jìn)程但是可能會(huì)有多個(gè)線程所以我們用得比較多的是多線程通信比如但是在一些特殊的情況下我們會(huì)需要多個(gè)進(jìn)程或者是我們?cè)谶h(yuǎn)程服務(wù)調(diào)用時(shí)就需要跨進(jìn)程通信了設(shè)置多進(jìn)程設(shè)置多進(jìn)程的步驟很 前言: 進(jìn)程間通信(Inter-Process Communication),簡稱IPC,就是指進(jìn)程與進(jìn)程之間進(jìn)行通信.一般來說,一個(gè)app只有一個(gè)...
閱讀 3081·2021-11-24 11:14
閱讀 3525·2021-11-22 15:22
閱讀 3215·2021-09-27 13:36
閱讀 726·2021-08-31 14:29
閱讀 1335·2019-08-30 15:55
閱讀 1768·2019-08-29 17:29
閱讀 1153·2019-08-29 16:24
閱讀 2417·2019-08-26 13:48