Android IPC機制(五)用Socket實現跨進程聊天程序

1.Socket簡介

Socket也稱作“套接字“,是在應用層和傳輸層之間的一個抽象層,它把TCP/IP層復雜的操作抽象為幾個簡單的接口供應用層調用以實現進程在網絡中通信。它分為流式套接字和數據包套接字,分別對應網絡傳輸控制層的TCP和UDP協議。TCP協議是一種面向連接的、可靠的、基于字節流的傳輸層通信協議。它使用三次握手協議建立連接,并且提供了超時重傳機制,具有很高的穩定性。UDP協議則是是一種無連接的協議,且不對傳送數據包進行可靠性保證,適合于一次傳輸少量數據,UDP傳輸的可靠性由應用層負責。在網絡質量令人十分不滿意的環境下,UDP協議數據包丟失會比較嚴重。但是由于UDP的特性:它不屬于連接型協議,因而具有資源消耗小,處理速度快的優點,所以通常音頻、視頻和普通數據在傳送時使用UDP較多。?
這里寫圖片描述

從上圖我們也可以看出,不同的用戶進程通過Socket來進行通信,所以Socket也是一種IPC方式,接下來我們用TCP服務來實現一個簡單的聊天程序。

2.實現聊天程序服務端

配置

首先我們來實現服務端,當然要使用Socket我們需要在AndroidManifest.xml聲明如下的權限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

我們需要實現一個遠程的Service來當作聊天程序的服務端,AndroidManifest.xml文件中配置service:

<serviceandroid:name=".SocketServerService"android:process=":remote" />

實現Service

接下來我們在Service啟動時,在線程中建立TCP服務,我們監聽的是8688端口,等待客戶端連接,當客戶端連接時就會生成Socket。通過每次創建的Socket就可以和不同的客戶端通信了。當客戶端斷開連接時,服務端也會關閉Socket并結束結束通話線程。服務端首先會向客戶端發送一條消息:“您好,我是服務端”,并接收客戶端發來的消息,將收到的消息進行加工再返回給客戶端。

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;@Overridepublic void onCreate() {new Thread(new TcpServer()).start();super.onCreate();}@Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.throw new UnsupportedOperationException("Not yet implemented");}private class TcpServer implements Runnable {@Overridepublic void run() {ServerSocket serverSocket;try {//監聽8688端口serverSocket = new ServerSocket(8688);} catch (IOException e) {return;}while (!isServiceDestroyed) {try {// 接受客戶端請求,并且阻塞直到接收到消息final Socket client = serverSocket.accept();new Thread() {@Overridepublic 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()));// 用于向客戶端發送消息PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);out.println("您好,我是服務端");while (!isServiceDestroyed) {String str = in.readLine();Log.i("moon", "收到客戶端發來的信息"   str);if (TextUtils.isEmpty(str)) {//客戶端斷開了連接Log.i("moon", "客戶端斷開連接");break;}String message = "收到了客戶端的信息為:"   str;// 從客戶端收到的消息加工再發送給客戶端out.println(message);}out.close();in.close();client.close();}@Overridepublic void onDestroy() {isServiceDestroyed = true;super.onDestroy();}
}

3.實現聊天程序客戶端

客戶端Activity會在onCreate方法中啟動服務端,并開啟線程連接服務端Socket。為了確保能連接成功,采用了超時重連的策略,每次連接失敗時都會重新建立連接。連接成功后,客戶端會收到服務端發送的消息:“您好,我是服務端”,我們也可以在EditText輸入字符并發送到服務端。

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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_socket);initView();Intent service = new Intent(this, SocketServerService.class);startService(service);new Thread() {@Overridepublic 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() {@Overridepublic void onClick(View v) {final String msg = et_receive.getText().toString();//向服務器發送信息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 {//選擇和服務器相同的端口8688socket = new Socket("localhost", 8688);mClientSocket = socket;mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);} catch (IOException e) {SystemClock.sleep(1000);}}try {// 接收服務器端的消息BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));while (!isFinishing()) {final String msg = br.readLine();if (msg != null) {runOnUiThread(new Runnable() {@Overridepublic void run() {tv_message.setText(tv_message.getText()   "\n"   "服務端:"   msg);}});}}mPrintWriter.close();br.close();socket.close();} catch (IOException e) {e.printStackTrace();}}}

布局很簡單(activity_socket.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@ id/tv_message"android:layout_width="match_parent"android:layout_height="400dp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:layout_alignParentBottom="true"android:orientation="horizontal"><EditTextandroid:id="@ id/et_receive"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="2"/><Buttonandroid:id="@ id/bt_send"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="向服務器發消息" /></LinearLayout>
</RelativeLayout>

4.運行聊天程序

運行程序,我們可以看到客戶端和服務端是兩個進程:?
這里寫圖片描述

客戶端首先會收到服務端的信息:”您好,我是服務端”,接下來我們向服務端發送“我想要怒放的生命”。這時候服務端收到了這條信息并返回給客戶端加工后的這條信息:?
這里寫圖片描述

  

  

https://github.com/henrymorgen/MoonSocket  

  

本文轉載于:猿2048?https://www.mk2048.com/blog/blog.php?id=bbjckkj&title=Android IPC機制(五)用Socket實現跨進程聊天程序

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/370512.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/370512.shtml
英文地址,請注明出處:http://en.pswp.cn/news/370512.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ArcGIS 網絡分析[4] 網絡數據集深入淺出之連通性、網絡數據集的屬性及轉彎要素...

前面介紹完了如何創建網絡數據集、如何使用網絡分析功能&#xff0c;當然還有的讀者會迷惑于一些更深層次的問題&#xff0c;比如網絡數據集的連通性問題等。 因為不可能面面俱到&#xff0c;我只能挑重點來闡述&#xff0c;我覺得網絡數據集的連通性、屬性和轉彎是初學者中比較…

java獲取byte 長度_java獲取字節的長度.

我們經常要獲取中文,數字,或者英文字符所占字節的長度,下面就列出各種編碼格式下所占字節的長度:代碼如下:package pack.java.midea.dao;import java.io.UnsupportedEncodingException;/*** 測試;* author zhouhaitao* 2012-5-17*/public class Test {/*** param args* throws …

Batoo JPA –比領先的JPA提供商快15倍

介紹 我早在2000年代就喜歡JPA 1.0。 我甚至在穩定版本發布之前就將其與EJB 3.0一起使用。 我非常喜歡它&#xff0c;因此我為JBoss 3.x實現貢獻了一些零碎的部分。 那時我們公司規模還很小。 創建新功能和應用程序比性能更重要&#xff0c;因為我們有很多想法&#xff0c;我…

python軟件是哪個國家的品牌_有哪些好用的軟件被國人誤認為是外國研發的?

國產軟件被標榜上了英文&#xff0c;即便不是英文&#xff0c;用拼音寫出來&#xff0c;也會有人誤認為是國外的軟件。因為這樣可以顯得高大上&#xff0c;為什么我們會有這樣的想法&#xff0c;是崇洋媚外嗎&#xff0c;并不是&#xff0c;而是之前的國產軟件的確有不少讓我們…

簡單的Session案例 —— 一次性驗證碼

一次性驗證碼的主要目的就是為了限制人們利用工具軟件來暴力猜測密碼&#xff0c;其原理與利用Session防止表單重復提交的原理基本一樣&#xff0c;只是將表單標識號變成了驗證碼的形式&#xff0c;并且要求用戶將提示的驗證碼手工填寫進一個表單字段中&#xff0c;而不是通過表…

[BZOJ2064]分裂

[BZOJ2064]分裂 試題描述 背景&#xff1a; 和久必分&#xff0c;分久必和。。。 題目描述&#xff1a; 中國歷史上上分分和和次數非常多。。通讀中國歷史的WJMZBMR表示毫無壓力。 同時經常搞OI的他把這個變成了一個數學模型。 假設中國的國土總和是不變的。 每個國家都可以用他…

CSS3選擇器

基本選擇器 回顧選擇器 通配符選擇器元素選擇器類選擇器ID選擇器后代選擇器新增基本選擇器 子元素選擇器相鄰兄弟選擇器通用兄弟選擇器群組選擇器 子元素選擇器 概念&#xff1a;子元素選擇器只能選擇某元素的子元素 語法&#xff1a;父元素 > 子元素 &#xff08;Fathe…

eclipse java工程目錄_轉載:Eclipse下的java工程目錄

對新手來講&#xff0c;一個Java工程內部的多個文件夾經常會讓大家困惑。更可惡的是莫名其妙的路徑問題&#xff0c;在Eclipse編寫Java程序中&#xff0c;出現頻率最高的錯誤很可能就是路徑問題。這些問題原因其實都是一個&#xff0c;就是關于Java工程內的文件結構理解不清&am…

作為JBoss AS 7模塊運行Drools 5.4.0 Final

Drools 5引入了業務邏輯集成平臺&#xff0c;該平臺為規則&#xff0c;工作流和事件處理提供了統一的集成平臺。 它是從頭開始設計的&#xff0c;因此每個方面都是一流的公民&#xff0c;毫不妥協。 Drools 5已分為4個主要子項目&#xff1a; Drools Guvnor&#xff08;BRMS …

postgres 支持的線程數_線程池被打滿了怎么處理呢,你是否真的了解線程池?

0、前言線程池&#xff0c;顧名思義就是線程的池子&#xff0c;在每次需要取線程去執行任務的時候&#xff0c;沒必要每次都創建新線程執行&#xff0c;線程池就是起著維護線程的作用&#xff0c;當有任務的時候就取出一個線程執行&#xff0c;如果任務執行完成則把線程放回到池…

[樹形DP]沒有上司的舞會

題目鏈接 思考 首先本題中的關系是一種樹形結構&#xff0c;而且符號最優子結構和無后效性&#xff0c;所以可以進行記憶化搜索。 那么首先要在這顆樹中選出一個點作為根節點&#xff0c;按照習慣我們將沒有父節點的點作為根節點。 接下來要思考的是 狀態&#xff1a; dp[i][0…

網頁自適應

1.viewport標簽 基本語法&#xff1a; <meta name”viewport” content”widthdevice-width,initial-scale1” /> 上面這行代碼的意思是&#xff0c;面積的100%&#xff0c;網頁寬度默認等于屏幕寬度&#xff08;widthdevice-width&#xff09;, 原始縮放比例&#x…

java 大數處理

頭文件&#xff1a;import java.util.*;import java.math.*; Scanner cin Scanner (System.in);//讀入while(cin.hasNext())//等價于!EOFncin.nextInt();//讀入一個int型的數ncin.nextBigInteger();//讀入一個大整數 輸出&#xff1a; System.out.print(n);//打印nSystem.out.…

java provider_Java SPI(Service Provider Interface)

//ServiceLoader實現了Iterable接口&#xff0c;可以遍歷所有的服務實現者public final class ServiceLoaderimplements Iterable{//查找配置文件的目錄private static final String PREFIX "META-INF/services/";//表示要被加載的服務的類或接口private final Clas…

帶有自定義注釋的Java注釋教程

Java注釋提供有關代碼的信息&#xff0c;并且它們對所注釋的代碼沒有直接影響。 在本教程中&#xff0c;我們將學習Java注釋&#xff0c;如何編寫自定義注釋 &#xff0c;注釋用法以及如何使用反射來解析注釋 。 注釋是在Java 1.5中引入的&#xff0c;現在它已在Hibernate&…

mybatis通用mapper_全網最全Mapper解析,附實操代碼幫你更好理解

今天給大家介紹一位老朋友當你第一次接觸Java開發的時候&#xff0c;這個老朋友就和你形影不離&#xff0c;當你要進行ORM的時候&#xff0c;單表的增刪改查&#xff0c;這位老朋友給了你極大的幫助&#xff0c;不知道你想到他了嗎&#xff1f;對&#xff0c;這就是通用mapper&…

初嘗微信小程序2-基本框架

基本框架&#xff1a; .wxml &#xff1a;頁面骨架 .wxss &#xff1a;頁面樣式 .js &#xff1a;頁面邏輯 描述一些行為 .json &#xff1a;頁面配置 創建一個小程序之后&#xff0c;app.js,app.json,app.wxss是必須的&#xff0c;而且名字也不能隨意更改&#xff0c;…

JSP內置對象,動作,指令總結

總的來說關于JSP界面有九大內置對象,7大動作,三大指令,現在博主就將這些粘貼出來,此文是很久前整理的學習筆記,如有雷同請諒解! jsp九大內置對象:1>out 向客戶端輸出數據,字節流.如out.print(" dgaweyr"); 2>request 接收客戶端的http請求.String getParameter…

洛谷 P1795 無窮的序列_NOI導刊2010提高(05)

P1795 無窮的序列_NOI導刊2010提高&#xff08;05&#xff09; 題目描述 有一個無窮序列如下&#xff1a; 110100100010000100000… 請你找出這個無窮序列中指定位置上的數字 輸入輸出格式 輸入格式&#xff1a;第一行一個正整數N&#xff0c;表示詢問次數&#xff1b; 接下來的…

java 取字符串中的數字_java截取字符串中的數字

隨便給你一個含有數字的字符串&#xff0c;比如&#xff1a;String s"eert343dfg56756dtry66fggg89dfgf";那我們如何把其中的數字提取出來呢&#xff1f;大致有以下幾種方法&#xff0c;正則表達式&#xff0c;集合類&#xff0c;還有就是String類提供的方法。1 Stri…