Android網路編程實踐之旅(二):基於Socket的網路通訊

來源:互聯網
上載者:User

        Socket(通訊端)是一種通訊機制,可以實現單機或跨網路進行通訊,其建立需要明確的區分C(用戶端)/S(伺服器端),支援多個用戶端串連到同一個伺服器。有兩種傳輸模式:

1)、連線導向的傳輸:基於TCP協議,可靠性高,但效率低;

2)、面向不需連線的傳輸:基於UDP協議,可靠性低,但效率高;

        Android中,直接採用Socket通訊應該是我們遇到的最低級的網路運用。儘管已經作了很大程度的抽象,但是純粹的Socket通訊,仍然給開發人員留下很多細節需要處理,尤其在伺服器端,開發人員需要處理多線程以及資料緩衝等的設計問題。相對而言,處於更高抽象層的HTTP等,已經對Socket通訊中需要處理的技術細節進行了很好的封裝,開發人員無須關心,因此,HTTP在網路開發中通常具有決定性的優勢。

        Android在其核心庫的java包中,提供了用於用戶端的Socket class和用於伺服器端的ServerSocket class,分別位於$SOURCE/libcore/luni/src/main/java/java/net/Socket.java和$SOURCE/libcore/luni/src/main/java/java/net/ServerSocket.java檔案中。分析兩個class的源碼,可以看出封裝考慮的很全面,只構造方法一向每個class都考慮了很多種使用方式。由於本人只是初學者,很多理解的不深入,這裡只拋磚引玉的對兩個class的構造方法分別介紹一種,就是我下面的程式中用到的:

Socket(String dstName, int dstPort):建立一個以流的方式(基於TCP協議)串連到目標機(這裡可以理解為伺服器)的用戶端Socket;dstName是目標機的IP地址,dstPort是要串連的目標機的端  口號。這裡要注意對連接埠的理解,它不能理解為物理上的一個介面,而是對電腦中一塊特殊記憶體地區的形象表述。

ServerSocket(int aport):建立一個綁定到本機指定連接埠的服務端Socket;aport就是指定的本機連接埠。與上述用戶端Socket對應,通過TCP串連時,ServerSocket建立後需要在aport連接埠上進行監聽,等待用戶端的串連。

        上面所寫都是些背景知識,下面對本人的編程實踐進行詳細說明。

1、功能描述

     1)、簡單的基於Socket的資料通訊;

     2)、採用TCP方式串連;

     3)、採用C/S結構,但服務端只支援一個串連;

     4)、用戶端能夠向服務端發送資料,並顯示服務端的返回資訊;

     5)、服務端能夠接收用戶端的資料,並將收到的資料以特定的方式返回給用戶端;

2、程式實現思路

    1)、服務端:設計為在後台執行的service,用一個獨立的線程來處理用戶端的串連請求、資料接收和返回。為了啟動該service,編寫個簡單的Activity。

    2)、用戶端:設計為一個Activity,介面由三部分組成:顯示服務端返回資訊的文本地區(一個文字框);進行資料輸入的編輯地區(一個編輯框);以及觸發串連請求並執行資料發送的觸發地區(一個按鈕)。

3、服務端來源程式

    1)、Activity檔案SocketServerDemo.java

package com.android.sample.SocketServerDemo;import android.app.Activity;import android.content.Intent;import android.os.Bundle;public class SocketServerDemo extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.main);System.out.println("begin start service"); this.startService(new Intent(this, SocketService.class));}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();this.stopService(new Intent(this, SocketService.class));}}

    2)、service檔案SocketService.java

package com.android.sample.SocketServerDemo;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;import android.app.Service;import android.content.Intent;import android.os.IBinder;public class SocketService extends Service{Thread mServiceThread;Socket client;@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();mServiceThread = new Thread(new SocketServerThread());}@Overridepublic void onStart(Intent intent, int startId) {// TODO Auto-generated method stubsuper.onStart(intent, startId);mServiceThread.start();}@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();}public class SocketServerThread extends Thread {private static final int PORT = 54321;private SocketServerThread(){}@Overridepublic void run() {try {ServerSocket server = new ServerSocket(PORT);while(true){System.out.println("begin client connected");client = server.accept();System.out.println("client connected");BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));System.out.println("read from client:");String textLine = reader.readLine();if(textLine.equalsIgnoreCase("EXIT")){System.out.println("EXIT invoked, closing client");break;}System.out.println(textLine);PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())));writer.println("ECHO from server: " + textLine);writer.flush();writer.close();reader.close();}} catch (IOException e) {// TODO Auto-generated catch blockSystem.err.println(e);}}    }}

    3)、AndroidManifest.xml檔案,因為需要在其中添加service和網路存取權限,這裡一併貼出

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="com.android.sample.SocketServerDemo"      android:versionCode="1"      android:versionName="1.0">    <uses-sdk android:minSdkVersion="9" />    <application android:icon="@drawable/icon" android:label="@string/app_name">        <activity android:name=".ScreenCastServer"                  android:label="@string/app_name">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>                <service android:name="com.android.sample.SocketServerDemo.SocketService">        </service>    </application>        <uses-permission android:name="android.permission.INTERNET"/></manifest>

4、用戶端程式

    1)、布局檔案main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    ><TextViewandroid:id="@+id/receive_msg"     android:layout_width="fill_parent"     android:layout_height="wrap_content"     />    <EditTextandroid:id="@+id/edit_msg"android:layout_width="fill_parent"android:layout_height="wrap_content"/><Buttonandroid:id="@+id/send_msg"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="send"/></LinearLayout>

    2)、Activity檔案SocketClientDemo.java

package com.android.sample.SocketClientDemo;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;import java.net.UnknownHostException;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class SocketClientDemo extends Activity {private static final String SERVERIP = "192.168.1.68";private static final int SERVERPORT = 54321;TextView mMsgRev;EditText mMsgEdit;Button   mMsgSendBtn;String mSendMsg;String mReceivedMsg;    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                mMsgRev = (TextView)findViewById(R.id.receive_msg);        mMsgEdit = (EditText)findViewById(R.id.edit_msg);        mMsgSendBtn = (Button)findViewById(R.id.send_msg);                mMsgSendBtn.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {Socket socket = null;mSendMsg = mMsgEdit.getText().toString();try {socket = new Socket(SERVERIP, SERVERPORT);PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));writer.println(mSendMsg);writer.flush();BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));mReceivedMsg = reader.readLine();if(mReceivedMsg != null){mMsgRev.setText(mReceivedMsg);}else{mMsgRev.setText("receive data error");}writer.close();reader.close();socket.close();} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}                });    }}

    3)、在AndroidManifest.xml中向伺服器端的該檔案一樣,添加網路存取權限:<uses-permission android:name="android.permission.INTERNET"/>

5、執行環境搭建

        服務端程式在開發板上執行,用戶端程式在模擬器上執行,實現了基於Socket的資料收發。但是我這裡只是進行了區域網路內的通訊,至於跨網路能不能行,目前條件不夠,沒法進行驗證。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.