Android Socket 通訊

Android socket 通訊

安卓編寫Socket客戶端,實現鏈接Socket服務端通訊。java

建立Socket鏈接並獲取服務端數據

先建立幾個全局變量吧android

private BufferedWriter writer = null;
Socket socket;

建立Socketjson

// 填好IPV4的IP地址和端口,服務端會提供,問服務端要
                socket = new Socket("192.168.1.156", 1234);
                // 下面三句照抄就行
                writer = new BufferedWriter(new OutputStreamWriter(
                        socket.getOutputStream()));
                InputStream inputStream = socket.getInputStream();
                DataInputStream input = new DataInputStream(inputStream);
                // 建立一個字節數組用來接收服務端發來的字節流,多大本身說了算
                byte[] b = new byte[100000];
                // 寫一個死循環,不停的接收服務端發來的數據
                while (true) {
                    // 將數據讀入字節數組,返回長度
                    int length = input.read(b);
                    // 若是服務端沒發數據就return不在往下執行,繼續讀數據
                    if (length <= 0) return;
                    // 若是服務端發的數據不爲空,則把字節數組轉成字符串
                    msg = new String(b, 0, length, "gb2312");
                    // 後邊就能夠調用數據解析的方法
                    ....
                }

通常的通信格式都是Json的,查一下把json格式的字符串轉換成json對象而後根據key值獲取value的代碼:數組

// 其中,data是json格式的字符串,轉換成了jsonObject對象
JSONObject jsonObject = new JSONObject(data);
// 獲取jsonObject對象的device_id值,固然device_id是String類型的,若是是int就用int
String i = jsonObject.getString("device_id");

發送數據給服務端

發送數據給服務端的前提是已經完成了Socket鏈接網絡

// 首先判斷一下socket是否是已經建立鏈接了,若是沒有就無論它
if (socket == null) return;
// str是準備發給服務端的字符串
writer.write(str);
// 發出去(留坑,繼續看完)
writer.flush();

這就完成了Android編寫Socket與服務端通訊的功能。可是這個Socket IPV4的地址能夠,IPV6的地址我沒試過,據說好像有點問題,可是大部分都用IPV4,若是真的用到IPV6的話,再百度!socket

糾錯

問題來咯!!!
我遇到的大坑!
在很早以前我開發的時候上面的操做編寫方式徹底沒問題!
可是,昨天我寫的時候發現會報錯!報錯在 writer.flush() 這個地方。
百度以後發現:
老版的android不會有問題,可是新版本的android(好像是sdk10以上)已經不容許在UI線程(主線程)中發起網絡請求了,會拋出NetWorkInUIThreadException。
因此說給服務端發送數據的時候須要寫到子線程裏。ide

new Thread(new Runnable() {
            @Override
            public void run() {
                // 首先判斷一下socket是否是已經建立鏈接了,若是沒有就無論它
                if (socket == null) return;
                // str是準備發給服務端的字符串
                writer.write("我是Android客戶端發的數據");
                // 發出去
                writer.flush();
            }
        }).start();

這樣就開一個子線程,在子線程中編寫發送數據的代碼或調用發送數據的方法就沒問題了!this

留坑!

生命不息,留坑不止!!
若是咱們把發送數據的代碼封裝成一個方法,而且發送的數據須要方法傳參,好比:線程

public void sendData(String str){
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 首先判斷一下socket是否是已經建立鏈接了,若是沒有就無論它
                if (socket == null) return;
                // str是準備發給服務端的字符串,會報錯,傳進來的參數子線程進不來
                writer.write(str);
                // 發出去
                writer.flush();
            }
        }).start();
}

發現父線程傳進的參數,子線程讀不到,我鬱悶了很久,本身寫了個內部類解決了。code

/**
     * 接口類,實現主線程向子線程傳值
     */
    class sendData implements Runnable {
        String str;
        public sendValueToServer(String str) {
            this.str = str;
        }
        @Override
        public void run() {
            try {
                // 若是socket鏈接失敗,則中止執行
                if (socket == null) return;
                // 發送傳進來的值
                writer.write(str);
                // 發出去
                writer.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

而後在須要發送的地方寫:

new Thread(new sendData ("傳值數據")).start();

完成!哈哈哈,刺激!

相關文章
相關標籤/搜索