1. 程式人生 > >Android客戶端與java伺服器端的Socket連線

Android客戶端與java伺服器端的Socket連線

開發十年,就只剩下這套架構體系了! >>>   

1.首先直接看伺服器端程式碼:

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.io.LineNumberReader;  

public class Server extends Thread {  

    private ServerSocket server = null; 
    private static final int PORT = 6000; 
    private BufferedWriter writer; 
    private BufferedReader reader;  

    private Server() throws IOException { 
        // 建立Socket伺服器 
        CreateSocket(); 
    }  

    public void run() { 
        Socket client; 
        String txt; 
        try { 
            // 執行緒無限迴圈,實時監聽socket埠 
            while (true){ 
                client = ResponseSocket();  

                // 響應客戶端連結請求。。 
                while (true) { 
                    txt = ReceiveMsg(client); 
                    // 連結獲得客戶端發來的命令 
                    System.out.println(txt); 
                    if (txt != null) { 
                        // 執行命令 
                        txt = exceCommand(txt); 
                    } 
                    // 向客戶端返回訊息 
                    SendMsg(client, txt); 
                    // 中斷,關閉此次連線 
                    break; 
                } 
                CloseSocket(client); 
            } 
        } catch (IOException e) { 
            System.out.println(e); 
        }  

    }  

    //建立一個ServerSocket例項,繫結到一個特定的埠。一個伺服器埠最多可以支援50個連結,超出了則拒絕連結。 
    //所以,最多隻能有50個客戶端同時使用這個指定的埠向伺服器傳送訊息 
    private void CreateSocket() throws IOException { 
        server = new ServerSocket(PORT); 
        System.out.println("Server starting.."); 
    }  

    /*
    ServerSocket:這個類是實現了一個伺服器端的Socket,利用這個類可以監聽來自網路的請求。
    1、建立ServerSocket的方法:
        ServerSocket(Int localPort)
        ServerSocket(int localport,int queueLimit)
        ServerSocket(int localport,int queueLimit,InetAddress localAddr)
        建立一個ServerSocket必須指定一個埠,以便客戶端能夠向該埠號傳送連線請求。埠的有效範圍是0-65535
  2、ServerSocket操作
        Socket accept()
        void close
        accept()方法為下一個傳入的連線請求建立Socket例項,並將已成功連線的Socket例項返回給伺服器套接字,如果沒有連線請求,
        accept()方法將阻塞等待;
        close方法用於關閉套接字
     */ 
    private Socket ResponseSocket() throws IOException { 
        Socket client = server.accept(); 
        System.out.println("client connected.."); 
        return client; 
    }  

    //關閉socket 
    private void CloseSocket(Socket socket) throws IOException { 
        reader.close(); 
        writer.close(); 
        socket.close(); 
        System.out.println("client closed.."); 
    }  

    //向客戶端傳送訊息 
    private void SendMsg(Socket socket, String Msg) throws IOException { 
        writer = new BufferedWriter(new OutputStreamWriter( 
                socket.getOutputStream())); 
        writer.write(Msg + "\n"); 
        writer.flush(); 
    }  

    //接收來自客戶端的訊息。伺服器通過server.accept();接收來自客戶端的套接字,採用I/O方式 
    //將套接字的訊息取出來 
    private String ReceiveMsg(Socket socket) throws IOException { 
        reader = new BufferedReader(new InputStreamReader( 
                socket.getInputStream())); 
        System.out.println("server get input from client socket.."); 
        String line = null; 
        while ((line = reader.readLine()) != null) { 
            System.out.println(line); 
            return line; 
        } 
        return line; 
    }  

    //執行客戶端傳送來的命令。伺服器將在本機執行客戶端傳送過來的訊息(命令)。 
    //並返回執行命令後,伺服器返回的結果。譬如,在linux下執行“ls”命令,返回的是當前目錄 
    //下面的所有檔案的名稱 
    private String exceCommand(String command) { 
        String msg = ""; 
        try { 
            //Runtime.getRuntime()返回當前應用程式的Runtime物件,該物件的exec() 
            //方法指示Java虛擬機器建立一個子程序執行指定的可執行程式(命令),並返回與該子程序對應的Process物件例項。 
            //通過Process可以控制該子程序的執行或獲取該子程序的資訊  

            Process process = Runtime.getRuntime().exec(command); 
            InputStreamReader ir = new InputStreamReader( 
                    process.getInputStream()); 
            LineNumberReader input = new LineNumberReader(ir); 
            String line; 
            while ((line = input.readLine()) != null) { 
                System.out.println(line); 
                msg += line + "\n"; 
            }  

        } catch (java.io.IOException e) { 
            System.err.println("IOException " + e.getMessage()); 
        }  

        return msg; 
    }  

    public static void main(final String args[]) throws IOException {  

        Server commandServer = new Server(); 
        if (commandServer != null) { 
//          commandServer.stop(); 
            commandServer.start(); 
        } 
    } 
}

2、Android客戶端activity_main.xml程式碼:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >
 
    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />
    <EditText 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edittext"
        android:hint="請輸入內容"
        />
    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="傳送"
        ></Button>
</LinearLayout>

3、Android客戶端Activity.java程式碼:

package com.example.socket2;
 
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
 
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
public class MainActivity extends Activity {
    //伺服器ip地址
    public static final String DEFULT_PRES = "192.168.56.1";
    public static final String PREFS_NAME = "PreferencesFile";
    public static final int CONNENTED = 0;
    public static final int UPDATALOG = 1;
    private static final int PORT = 6000;
    private EditText command;
    private TextView log;
    private Button send;
    private String ip;
    private String logMsg;
    private Socket socket;
    private BufferedWriter writer;
    private InetSocketAddress isa = null;
    Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
 
            case CONNENTED:
                logMsg += "Server Connented\n";
                log.setText(logMsg);
                break;
 
            case UPDATALOG:
                log.setText(logMsg);
                log.setScrollContainer(true);
                break;
            }
        }
    };
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findviews();
        init();
        setonclick();
    }
 
    public void findviews() {
        command = (EditText) this.findViewById(R.id.edittext);
        log = (TextView) this.findViewById(R.id.textview);
        send = (Button) this.findViewById(R.id.send);
    }
 
    private void init() {
        log.setMovementMethod(ScrollingMovementMethod.getInstance());
        logMsg = log.getText().toString();
        //建立一個socket例項
        socket = new Socket();
        ip ="192.168.56.1" ;
    }
 
    private void setonclick() {
        send.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                ip = "192.168.56.1";
                //當點擊發送按鈕時,開啟一個tcpClient執行緒,向伺服器傳送訊息
                tcpClient tcp = new tcpClient(command.getText().toString());
                tcp.start();
            }
        });
 
 
    }
    class tcpClient extends Thread {
        String commandString;
 
        public tcpClient() {
            commandString = "ls";
        }
 
        public tcpClient(String command) {
            commandString = command;
        }
 
        public void run() {
            String recv;
            try {
                Socket ConSocket = new Socket();
                //建立套接字地址,其中 IP 地址為萬用字元地址,埠號為指定值。
                //有效埠值介於 0 和 65535 之間。埠號 zero 允許系統在 bind 操作中挑選暫時的埠。 
                isa = new InetSocketAddress(ip, PORT);
                //建立一個遠端連結
                ConSocket.connect(isa);
                //socket.connect(isa);
                socket=ConSocket;
                if (socket.isConnected()) {
                    Message msg = new Message();
                    msg.what = CONNENTED;
                    mHandler.sendMessage(msg);
                }
                //向伺服器傳送命令
                writer = new BufferedWriter(new OutputStreamWriter(
                        socket.getOutputStream()));
 
                Log.i("msg", commandString.replace("\n", "")+"\n");
                writer.write(commandString.replace("\n", "")+"\n");
                writer.flush();
                //等待,接收來自伺服器返回的訊息
                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        socket.getInputStream()));
                String line;
                String txt = "";
                while ((line = reader.readLine()) != null) {
                    txt += line + "\n";
                } 
                reader.close();
                recv = txt;
 
                if (recv != null) {
                    logMsg += recv;
                    // close BufferedWriter and socket
                    writer.close();
                    socket.close();
                    // 將伺服器返回的訊息顯示出來
                    Message msg = new Message();
                    msg.what = UPDATALOG;
                    mHandler.sendMessage(msg);
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4、在清單檔案中增加兩條授權:(重要)

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