安卓編寫Socket客戶端,實現鏈接Socket服務端通訊。java
先建立幾個全局變量吧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();
完成!哈哈哈,刺激!