Android Socket 通信


Android socket 通信

安卓編寫Socket客戶端,實現連接Socket服務端通信。

創建Socket連接並獲取服務端數據

先創建幾個全局變量吧

private BufferedWriter writer = null;
Socket socket;

創建Socket

                // 填好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的話,再百度!

糾錯

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

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

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

留坑!

生命不息,留坑不止!!
如果我們把發送數據的代碼封裝成一個方法,並且發送的數據需要方法傳參,比如:

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();
}

發現父線程傳進的參數,子線程讀不到,我郁悶了好久,自己寫了個內部類解決了。

    /**
     * 接口類,實現主線程向子線程傳值
     */
    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();

完成!哈哈哈,刺激!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM