[Android] Android 學習筆記:開啟一個 server socket

[Android] Android 學習筆記:開啟一個 server socket

如果想讓 app 可以開一個 port 等待外界傳資料進來,應該要怎麼做呢?

其實這個跟 Android 沒什麼關係,而是用 Java 的 ServerSocket 元件就可以作到了~

只是因為 server socket 在 accept() 的時候,執行緒會卡住,

因此應該要開一個新的執行緒來執行~

 

下面的程式片段開了一個 8888 的 server port,

接著啟動一個新的執行緒 MyServerThread 來做接下來的動作~

(這裡的 MyServerThread 是一個繼承自 Thread 的類別)

要注意的是 socket 的動作通常都需要用 try/catch 包起來,

因為有丟 exception 的可能性~

try
{
    // Open a server socket
    int nServerPort = 8888;
    m_serverSocket = new ServerSocket(nServerPort);
   
    // Start a server thread to do socket-accept tasks
    MyServerThread serverThread = new MyServerThread(MyActivity.this);
    serverThread.start();
}
catch (IOException e)
{
    e.printStackTrace();
} 

 

要關閉 server socket 也很容易,呼叫 close() 就可以了:

try
{
    // Close server socket
    m_serverSocket.close();
}
catch (IOException e)
{
    e.printStackTrace();
}        

 

等待接收 client 連線的部分,呼叫 accept() 函式就可以了~

Socket socketClient = m_serverSocket.accept();

 

下面的範例程式是一個較完整的程式,當按下 ToggleButton 時,

會開啟 server socket 聽在 8888 port,再按一下則會關閉~ 

 

MyActivity.java:

package com.my;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ToggleButton;

import java.io.IOException;
import java.net.ServerSocket;

import com.my.R;

public class MyActivity extends Activity {
   
    // Public variables
    public ServerSocket     m_serverSocket      = null;

    // Private Controls
    private ToggleButton    m_toggleButtonServerOnOff;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        // Initialize control variables
        m_toggleButtonServerOnOff       = (ToggleButton)findViewById(R.id.toggleButtonServerOnOff);
       
        // Set listener functions
        m_toggleButtonServerOnOff.setOnClickListener(onToggleServerOnOff);
    }
   
    private Button.OnClickListener onToggleServerOnOff = new Button.OnClickListener(){
        public void onClick(View v)
        {
            if (m_toggleButtonServerOnOff.isChecked())
            {
                try
                {
                    // Open a server socket
                    int nServerPort = 8888;
                    m_serverSocket = new ServerSocket(nServerPort);
                   
                    // Start a server thread to do socket-accept tasks
                    MyServerThread serverThread = new MyServerThread(MyActivity.this);
                    serverThread.start();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            else
            {
                try
                {
                    // Close server socket
                    m_serverSocket.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }              
            }
        }
    };
}

 

另一段則是真正在接收 socket 連線的 MyServerThread 的程式~

它在建構式裡先把 activity 的指標存起來,

接著覆寫 run() 函式,呼叫 ServerSocket::accept() 函式來等待 client 的連線~

當連線成功時,用 DataInputStream 把送進來的文字資訊一行行讀出來,

並輸出到 logging 機制去~

 

MyServerThread.java:

/**
 *
 */

package com.my;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import android.util.Log;

public class MyServerThread extends Thread {

    private static final String LOG_TAG = “MyServerThread”;
   
    private MyActivity  m_activityMain;
   
    public MyServerThread(MyActivity activityMain)
    {
        super();
       
        // Save the activity
        m_activityMain = activityMain;
    }

    @Override
    public void run()
    {
        while (true)
        {
            try
            {
                // Wait for new client connection
                Log.i(LOG_TAG, “Waiting for client connection…”);
                Socket socketClient = m_activityMain.m_serverSocket.accept();
               
                Log.i(LOG_TAG, “Accepted connection from “ + socketClient.getInetAddress().getHostAddress());
                       
                // Read input from client socket
                InputStream is = socketClient.getInputStream();
                OutputStream os = socketClient.getOutputStream();
                DataInputStream dis = new DataInputStream(is);
                while (!socketClient.isClosed())
                {
                    // Read a line
                    String sLine = dis.readLine();
                    Log.i(LOG_TAG, “Read client socket=[“ + sLine + “]”);
                    if (sLine == null)
                    {
                        break;
                    }
                }
               
                // Close streams
                dis.close();
                os.close();
                is.close();
               
                // Close client socket
                Log.i(LOG_TAG, “Read data from client ok. Close connection from “ + socketClient.getInetAddress().getHostAddress());
                socketClient.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
           
            // Stop loop when server socket is closed
            if (m_activityMain.m_serverSocket.isClosed())
            {
                break;
            }
        }
    }

}

 

 

(本頁面已被瀏覽過 3,195 次)

2 thoughts on “[Android] Android 學習筆記:開啟一個 server socket

  1. 版主您好,再server端部分怎麼沒有看到綁port 的code 呢?
    版主回覆:(03/06/2015 03:16:24 PM)
    嗯?下面這個就是囉:
    // Open a server socket
    int nServerPort = 8888;
    m_serverSocket = new ServerSocket(nServerPort);

  2. 版主您好~
    請問 ServerSocket 有辦法測量出傳輸的頻寬多大嗎?

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料