1. 程式人生 > >Android程序間通訊(IPC)之Socket

Android程序間通訊(IPC)之Socket

Socket也被稱為“套接字”程式設計,它分為流式套接字和使用者資料套接字兩種,分別對應於網路傳輸控制中層中TCP和UDP協議。TCP協議是面向連線的協議,提供穩定的雙向通訊功能,TCP連線的建立需要經過”三次握手”才能實現,為了實現穩定的資料傳輸功能,其本身提供了超時重傳機制,具有很高的穩定性。UDP是無連線的,提供不穩定的單向通訊功能,當然UDP也可以實現雙向通訊功能,在效能上,UDP就有更好的效率,其缺點是不能保證資料一定傳輸正確,尤其是網路擁塞的情況下。
演示一個Socket聊天的程式:

服務端

package com.app.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.io.UnsupportedEncodingException; import java.net.ServerSocket; import java.net.Socket; import java.util.Random; import android.app.Service; import
android.content.Intent; import android.os.IBinder; import android.util.Log; public class TcpService extends Service { private boolean mIsServiceDestoryed = false; private String[] mDefinedMessage = new String[] { "你好", "hello", "辛苦了" }; private ServerSocket mServerSocket; @Override
public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); new Thread(new TcpThread()).start(); } class TcpThread implements Runnable { @Override public void run() { try { //服務端在8688這個埠監聽 mServerSocket = new ServerSocket(8688); } catch (IOException e) { e.printStackTrace(); return; } while (!mIsServiceDestoryed) { try { //一個阻塞的方法,當有客戶端Socket時會執行 final Socket socket = mServerSocket.accept(); new Thread() { @Override public void run() { responseClient(socket); } }.start(); } catch (IOException e) { e.printStackTrace(); } } } } //服務端相應客戶端 private void responseClient(Socket socket) { try { //讀取客戶端發來的訊息 BufferedReader in = new BufferedReader(new InputStreamReader( socket.getInputStream())); //用於向客戶端傳送訊息 PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())), true); out.println("歡迎來到聊天室!"); while (!mIsServiceDestoryed) { String str = in.readLine();//通訊連線後,客戶端不發訊息,這個方法會一直阻塞 Log.e("tag", "客戶端訊息:====" + str); if (str == null) { break; } int i = new Random().nextInt(mDefinedMessage.length); String msg = mDefinedMessage[i]; out.println(msg);//向客戶端傳送訊息 } //客戶端連線斷開後,要關閉資料流 in.close(); out.close(); socket.close(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onDestroy() { mIsServiceDestoryed = true;//停止執行緒 super.onDestroy(); } }

客戶端
先看佈局程式碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#fff"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/et_recore"
        android:layout_width="fill_parent"
        android:layout_height="200dip"
        android:gravity="top|left"
        android:text="聊天記錄:\n" >
    </EditText>

    <EditText
        android:id="@+id/et_send_content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="輸入要傳送的內容" >
    </EditText>

    <Button
        android:id="@+id/btn_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="傳送"
        android:textColor="#000" />

</LinearLayout>

java程式碼:

package com.app.client;

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.io.UnsupportedEncodingException;
import java.net.Socket;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {
    private static final int MESSAGE_RECEIVE_NEW_MSG = 1;
    private static final int MESSAGE_SOCKET_CONNECTED = 2;
    private Button mButton_Send;
    private EditText mEditText01, mEditText02;
    private PrintWriter mPintWriter;
    private Socket mClientSocket;

    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_RECEIVE_NEW_MSG:
                mEditText01.setText(mEditText01.getText() + (String) msg.obj);
                break;
            case MESSAGE_SOCKET_CONNECTED:
                mButton_Send.setEnabled(true);
                mEditText02.setEnabled(true);
                break;

            default:
                break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton_Send = (Button) findViewById(R.id.btn_send);
        mEditText01 = (EditText) findViewById(R.id.et_recore);
        mEditText02 = (EditText) findViewById(R.id.et_send_content);
        mButton_Send.setEnabled(false);
        mButton_Send.setOnClickListener(this);
        //開啟服務
        Intent i = new Intent("com.app.service");
        startService(i);
        new Thread() {
            @Override
            public void run() {
                connectTCPServer();
            }
        }.start();
    }

    protected void connectTCPServer() {
        Socket socket = null;
        //while裡面使用了超時重連策略
        while (socket == null) {
            try {
                socket = new Socket("localhost", 8688);
                mClientSocket = socket;
                mPintWriter = new PrintWriter(new BufferedWriter(
                        new OutputStreamWriter(socket.getOutputStream())), true);
                mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED);
            } catch (Exception e) {
                SystemClock.sleep(1000);
            }
        }
        try {
            //用於讀取服務端的訊息
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    mClientSocket.getInputStream(), "utf-8"));
            while (!MainActivity.this.isFinishing()) {
                String msg = br.readLine();//讀取
                Log.e("tag", "服務端訊息:====" + msg);
                if (msg != null) {
                    String showeMsg = "server : " + msg + "\n";
                    mHandler.obtainMessage(MESSAGE_RECEIVE_NEW_MSG, showeMsg)
                            .sendToTarget();
                }
            }
            //關閉資源
            mPintWriter.close();
            br.close();
            socket.close();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onClick(View v) {
        String msg = mEditText02.getText().toString();
        if (!TextUtils.isEmpty(msg) && mPintWriter != null) {
            mPintWriter.println(msg);
            mEditText02.setText("");
            String showMsg = "client : " + msg + "\n";
            mEditText01.setText(mEditText01.getText() + showMsg);
        }
    }

    @Override
    protected void onDestroy() {
        if (mClientSocket != null) {
            try {
                mClientSocket.shutdownInput();
                mClientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        super.onDestroy();
    }
}

客戶端和服務端聯網需要許可權:

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

相關推薦

Android程序通訊(IPC)Socket

Socket也被稱為“套接字”程式設計,它分為流式套接字和使用者資料套接字兩種,分別對應於網路傳輸控制中層中TCP和UDP協議。TCP協議是面向連線的協議,提供穩定的雙向通訊功能,TCP連線的建立需要經過”三次握手”才能實現,為了實現穩定的資料傳輸功能,其本身提

Linux---程序通訊IPC管道

**程序間通訊(IPC):**是指在不同程序之間傳播或交換資訊。 **IPC的方式:**通常有管道(無名管道、命名管道)、訊息佇列、訊號量、共享儲存、Socket、Streams等(Socket和Streams支援不同主機上的兩個程序IPC) 程序間通訊的目的:

程序通訊(IPC)訊息佇列

★IPC方法包括管道(PIPE)、訊息佇列(Message_Queue)、旗語、共用記憶體(ShareMemory)以及套接字(Socket)。進 程間通訊主要包括了管道、系統IPC(包括了訊息佇列、

Linux---程序通訊IPC訊息佇列

**程序間通訊(IPC):**是指在不同程序之間傳播或交換資訊。 **IPC的方式:**通常有管道(無名管道、命名管道)、訊息佇列、訊號量、共享儲存、Socket、Streams等(Socket和Streams支援不同主機上的兩個程序IPC) 程序間通訊的目

程序通訊(IPC)訊號量

★IPC方法包括管道(PIPE)、訊息佇列(Message_Queue)、訊號量(semaphore)、共用記憶體 (ShareMemory)以及套接字(Socket)。程序間通訊主要包括了管道、系統IPC(包括了訊息佇列、訊號以 及共享儲存)、套接字(SOCKET)。此文

Linux---程序通訊IPC共享記憶體

程序間通訊(IPC):是指在不同程序之間傳播或交換資訊。 IPC的方式:通常有管道(無名管道、命名管道)、訊息佇列、訊號量、共享儲存、Socket、Streams等(Socket和Streams支援不同主機上的兩個程序IPC) 程序間通訊的目的: 1

Android程序通訊Socket

Socket也稱為“套接字”,是網路通訊中的概念,它分為流式套接字和使用者資料報套接字兩種,分別對應於網路傳輸控制層中的TCP和UDP協議。 TCP協議是面向連線的協議,提供穩定的雙向通訊功能,TCP連線的建立需要經過“三次握手”才能完成,為了提供穩定的資料傳輸功能,其本身

Android程序通訊 - Socket使用(TCP、UDP)

在使用Socket實現程序間通訊前,先對網路協議相關知識進行簡單回顧。 網路分層 一般情況會將網路分為5層: 應用層     常見協議:HTTP、FTP、POP3等 傳輸層     

Android系統程序通訊 IPC 機制Binder中的Server啟動過程原始碼分析

                        在前面一篇文章中,介紹了在Android系統中Binder程序間通訊機制中的Server角色是如何獲得Service Manager遠端介面的,即defaultServiceManager函式的實現。Server獲得了Service Manager遠端介面之後,

Android-Android程序通訊messenger

轉自‘https://www.cnblogs.com/makaruila/p/4869912.html 平時一說程序間通訊,大家都會想到AIDL,其實messenger和AIDL作用一樣,都可以進行程序間通訊。它是基於訊息的程序間通訊,就像子執行緒和UI執行緒傳送訊息那樣,是不是很簡單,還不用去寫AIDL檔

[心得]Android程序通訊Broadcast Receiver

Android框架層提供的一些通訊機制Broadcast、Intent、Content Provider,主要用於應用程式開發時提供跨程序或應用程式內部的通訊。 android中,通過廣播(broadcast)可以通知廣播接受者某個事件發生了。比如一些系統時間:電源不足,

Android程序通訊IPC)機制Binder簡要介紹和學習計劃

轉載:http://blog.csdn.net/luoshengyang/article/details/6618363/在Android系統中,每一個應用程式都是由一些Activity和Service組成的,這些Activity和Service有可能執行在同一個程序中,也有

android程序通訊--Binder

深入理解之程序間通訊–Binder 同一個程式中的兩個方法能夠直接呼叫的根本原因是處於相同的記憶體空間中。兩個不同的應用程式因為不在同一個程序中,他們是沒有辦法直接通過記憶體地址來訪問到對方的函式和變數的。同一個程序中物件的傳遞是傳遞的記憶體地址,這個地址並不是真正的實體地址,而是邏

Android程序通訊——ContentProvider的使用

前言 ContentProvider作為四大元件之一,一直以來存在感都很低,但其實它的功能還是很強大的,尤其是在實現程序間通訊的時候。和AIDL一樣,ContentProvider的底層實現也是Binder,但是由於系統已經為我們做了封裝,所以它的使用過程要簡單的多。 一、什麼是Conten

Linux程序通訊IPC的幾種方式簡介

Linux程序通訊的源頭       linux下的程序通訊手段基本上是從Unix平臺上的程序通訊手段繼承而來的。而對Unix發展做出重大貢獻的兩大主力AT&T(原為American Telephone & Tele

Android程序通訊 - 幾種方式的對比總結

什麼是RPC RPC(Remote Procedure Call)即遠端過程呼叫,它是一種通過網路從遠端計算機程式上請求服務,在不需要了解底層網路技術的協議下,即可獲取計算機程序中的資料。RPC使得開發包括網路分散式多程式在內的應用程式更加容易。 RPC在OSI網路通訊7層模型中

Android程序通訊 - ContentProvider內容提供者

簡介 ContentProvider主要用於在不同的應用程式間實現資料共享的功能,允許一個程式訪問另外一個程式中的資料,還能保證資料訪問的安全性。 是Android跨程序實現資料共享的標準方式。 ContentProvider相當於程序間的搬運工,

Android程序通訊的幾種方式

定義多程序 Android應用中使用多程序只有一個辦法(用NDK的fork來做除外),就是在AndroidManifest.xml中宣告元件時,用android:process屬性來指定。 不知定process屬性,則預設執行在主程序中,主程序名字為包名。 andr

android程序通訊:使用AIDL

  from: http://blog.csdn.net/saintswordsman/article/details/5130947 歡迎閱讀本文,你能關注本文,你知道你需要程序間通訊、需要AIDL(以及Binder),那麼可以預設你對這些概念已經有了一些

Linux程序通訊方式--本地socket

先上一個程式碼 服務端: //s_unix.c #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #