http://www.javashuo.com/article/p-sqrbiaas-bg.htmlhtml
先作接收消息數組
而後接着緩存
public class MainActivity extends AppCompatActivity { EditText editTextActivityMain1,editTextActivityMain2;//定義兩個EditText變量,變量名字我通常設置的和先前頁面裏面的同樣 Button buttonActivityMain1;//鏈接按鈕 Socket socket;//定義一個Socket MyHandler myHandler; private OutputStream outputStream;//TCP發送數據使用 private InputStream inputStream;//TCP接收數據使用 byte[] TcpReceiveData = new byte[1024];//用來緩存接收的數據 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myHandler = new MyHandler(); //獲取控件 editTextActivityMain1 = findViewById(R.id.editTextActivityMain1); editTextActivityMain2 = findViewById(R.id.editTextActivityMain2); buttonActivityMain1 = findViewById(R.id.buttonActivityMain1); buttonActivityMain1.setText("鏈接");//加上這個,不然按鈕須要點擊兩次纔會判斷按鈕的Text是"鏈接" //鏈接按鈕點擊事件 buttonActivityMain1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (buttonActivityMain1.getText().toString() == "鏈接"){ new Thread(new Runnable() { @Override public void run() { //這裏面寫具體的程序 try { socket = new Socket(editTextActivityMain1.getText().toString(),Integer.valueOf(editTextActivityMain2.getText().toString()));//鏈接TCP服務器 if (socket.isConnected()){//若是鏈接上TCP服務器 Log.e("MainActivity", "isConnected"); Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 1;//設置消息變量的 what 變量值 爲1 myHandler.sendMessage(msg);//插入消息隊列 outputStream = socket.getOutputStream();//獲取輸出數據流 inputStream = socket.getInputStream();//獲取輸入數據流 TcpClientReceive();//加載接收函數 } } catch (Exception e){ Log.e("MainActivity", e.toString()); } } }).start(); } else { try{ socket.close(); }catch (Exception e){} //關閉鏈接 try{ inputStream.close(); }catch (Exception e){} //關閉數據流 buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接 } } }); } //TCP客戶端接收數據 public void TcpClientReceive(){ new Thread(new Runnable() { @Override public void run() { while(socket.isConnected()){//若是客戶端一直鏈接着就一直在任務裏面 try{ int TcpReceiveDataLen = inputStream.read(TcpReceiveData);//接收數據,服務器斷開會返回-1 if(TcpReceiveDataLen!=-1){ byte[] Buffer = new byte[TcpReceiveDataLen];//建立一個新的數組 System.arraycopy(TcpReceiveData, 0, Buffer, 0, TcpReceiveDataLen);//拷貝數據 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 2;//設置消息變量 msg.obj = Buffer;//obj 能夠接收任意類型的變量 myHandler.sendMessage(msg);//插入消息隊列 } else{//斷開了鏈接 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 9;//設置消息變量 myHandler.sendMessage(msg);//插入消息隊列 } }catch (Exception e){//接收數據有錯誤 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 9;//設置消息變量 myHandler.sendMessage(msg);//插入消息隊列 } } } }).start(); } //Handler class MyHandler extends Handler { public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1){//接收到消息變量的 what 變量值 爲1 buttonActivityMain1.setText("斷開");//按鈕顯示斷開 } else if (msg.what == 2){//接收到消息變量的 what 變量值 爲2 try{ byte[] TcpReadData = (byte[])msg.obj;//接收消息 Log.e("MainActivity", new String(TcpReadData) );//打印消息 }catch (Exception e){} } else if (msg.what == 9){//接收到消息變量的 what 變量值 爲9 try{ socket.close(); }catch (Exception e){} //關閉鏈接 try{ inputStream.close(); }catch (Exception e){} //關閉鏈接 buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接 } } } }
測試Android 接收數據服務器
測試服務器忽然故障app
稍等,,我仍是直接打印一下日誌比較好socket
................有BUGide
加上break;函數
再測試測試
public class MainActivity extends AppCompatActivity { EditText editTextActivityMain1,editTextActivityMain2;//定義兩個EditText變量,變量名字我通常設置的和先前頁面裏面的同樣 Button buttonActivityMain1;//鏈接按鈕 Socket socket;//定義一個Socket MyHandler myHandler; private OutputStream outputStream;//TCP發送數據使用 private InputStream inputStream;//TCP接收數據使用 byte[] TcpReceiveData = new byte[1024];//用來緩存接收的數據 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myHandler = new MyHandler(); //獲取控件 editTextActivityMain1 = findViewById(R.id.editTextActivityMain1); editTextActivityMain2 = findViewById(R.id.editTextActivityMain2); buttonActivityMain1 = findViewById(R.id.buttonActivityMain1); buttonActivityMain1.setText("鏈接");//加上這個,不然按鈕須要點擊兩次纔會判斷按鈕的Text是"鏈接" //鏈接按鈕點擊事件 buttonActivityMain1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (buttonActivityMain1.getText().toString() == "鏈接"){ new Thread(new Runnable() { @Override public void run() { //這裏面寫具體的程序 try { socket = new Socket(editTextActivityMain1.getText().toString(),Integer.valueOf(editTextActivityMain2.getText().toString()));//鏈接TCP服務器 if (socket.isConnected()){//若是鏈接上TCP服務器 Log.e("MainActivity", "isConnected"); Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 1;//設置消息變量的 what 變量值 爲1 myHandler.sendMessage(msg);//插入消息隊列 outputStream = socket.getOutputStream();//獲取輸出數據流 inputStream = socket.getInputStream();//獲取輸入數據流 TcpClientReceive();//加載接收函數 } } catch (Exception e){ Log.e("MainActivity", e.toString()); } } }).start(); } else { try{ socket.close(); }catch (Exception e){} //關閉鏈接 try{ inputStream.close(); }catch (Exception e){} //關閉數據流 buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接 } } }); } //TCP客戶端接收數據 public void TcpClientReceive(){ new Thread(new Runnable() { @Override public void run() { while(socket.isConnected()){//若是客戶端一直鏈接着就一直在任務裏面 try{ int TcpReceiveDataLen = inputStream.read(TcpReceiveData);//接收數據,服務器斷開會返回-1 if(TcpReceiveDataLen!=-1){ byte[] Buffer = new byte[TcpReceiveDataLen];//建立一個新的數組 System.arraycopy(TcpReceiveData, 0, Buffer, 0, TcpReceiveDataLen);//拷貝數據 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 2;//設置消息變量 msg.obj = Buffer;//obj 能夠接收任意類型的變量 myHandler.sendMessage(msg);//插入消息隊列 } else{//斷開了鏈接 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 9;//設置消息變量 myHandler.sendMessage(msg);//插入消息隊列 break; } }catch (Exception e){//接收數據有錯誤 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 9;//設置消息變量 myHandler.sendMessage(msg);//插入消息隊列 break; } } } }).start(); } //Handler class MyHandler extends Handler { public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1){//接收到消息變量的 what 變量值 爲1 buttonActivityMain1.setText("斷開");//按鈕顯示斷開 } else if (msg.what == 2){//接收到消息變量的 what 變量值 爲2 try{ byte[] TcpReadData = (byte[])msg.obj;//接收消息 Log.e("MainActivity", new String(TcpReadData) );//打印消息 }catch (Exception e){} } else if (msg.what == 9){//接收到消息變量的 what 變量值 爲9 try{ socket.close(); }catch (Exception e){} //關閉鏈接 try{ inputStream.close(); }catch (Exception e){} //關閉鏈接 buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接 Log.e("MainActivity", "和服務器斷開鏈接!!!" );//打印消息 } } } }
如今作一下發送和接收數據的頁面字體
點擊這個,改成百分比
拖到50%
我更改了背景色,和顯示字體的顏色
如今把接收的數據顯示出來
測試
如今作一個顯示16進制和字符串切換的
其實咱接收過來的就是16進制,咱須要把16進制轉化爲16進制字符串
/** * 16進制byte轉16進制String--用空格隔開 * @param bytes * @return */ public static String byteToHexStr(byte[] bytes) { String str_msg = ""; for (int i = 0; i < bytes.length; i++){ str_msg = str_msg + String.format("%02X",bytes[i])+" "; } return str_msg; }
測試
不過看一下,在這個位置顯示的...咱修改下
首先說一點
發送數據都是給個數組
因此
添加上格式
實際上咱獲取的文本框裏面的都是字符串
咱須要把字符串轉化爲 列如: "33" ==> 0x33
/** * 將已十六進制編碼後的字符串src,以每兩個字符分割轉換爲16進制形式 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF, * 0xD9} * * @param src * String * @return byte[] */ public static byte[] HexString2Bytes(String str) { StringBuilder sb = null; String src = null; if ((str.length()%2)!=0) {//數據不是偶數 sb = new StringBuilder(str);//構造一個StringBuilder對象 sb.insert(str.length()-1, "0");//在指定的位置1,插入指定的字符串 src = sb.toString(); } else { src = str; } Log.e("error", "str.length()"+str.length()); byte[] ret = new byte[src.length() / 2]; byte[] tmp = src.getBytes(); for (int i = 0; i < tmp.length / 2; i++) { ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]); } return ret; } /** * 將兩個ASCII字符合成一個字節; 如:"EF"--> 0xEF * * @param src0 * byte * @param src1 * byte * @return byte */ public static byte uniteBytes(byte src0, byte src1) { try { byte _b0 = Byte.decode("0x"+new String(new byte[] { src0 })) .byteValue(); _b0 = (byte) (_b0 << 4); byte _b1 = Byte.decode("0x"+new String(new byte[] { src1 })) .byteValue(); byte ret = (byte) (_b0 ^ _b1); return ret; } catch (Exception e) { // TODO: handle exception } return 0; }
public class MainActivity extends AppCompatActivity { EditText editTextActivityMain1,editTextActivityMain2,editTextActivityMain3;//IP,端口號,發送數據框 Button buttonActivityMain1,buttonActivityMain2,buttonActivityMain3;//鏈接按鈕,發送,清除接收 TextView textViewActivityMain4;//接收文本 CheckBox checkBoxActivityMain1,checkBoxActivityMain2;//切換顯示,發送格式選擇 Socket socket;//定義一個Socket MyHandler myHandler; private OutputStream outputStream;//TCP發送數據使用 private InputStream inputStream;//TCP接收數據使用 byte[] TcpReceiveData = new byte[1024];//用來緩存接收的數據 byte[] TcpSendData = new byte[1024];//用來緩存發送的數據 int TcpSendDataLen =0;//發送的數據個數 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); myHandler = new MyHandler(); //獲取控件 editTextActivityMain1 = findViewById(R.id.editTextActivityMain1);//IP editTextActivityMain2 = findViewById(R.id.editTextActivityMain2);//端口號 editTextActivityMain3 = findViewById(R.id.editTextActivityMain3);//發送數據框 buttonActivityMain1 = findViewById(R.id.buttonActivityMain1);//鏈接按鈕 buttonActivityMain2 = findViewById(R.id.buttonActivityMain2);//發送數據 buttonActivityMain3 = findViewById(R.id.buttonActivityMain3);//清除接收 textViewActivityMain4 = findViewById(R.id.textViewActivityMain4);//接收數據文本 checkBoxActivityMain1 = findViewById(R.id.checkBoxActivityMain1);//切換顯示 checkBoxActivityMain2 = findViewById(R.id.checkBoxActivityMain2);//發送格式選擇 buttonActivityMain1.setText("鏈接");//加上這個,不然按鈕須要點擊兩次纔會判斷按鈕的Text是"鏈接" //鏈接按鈕點擊事件 buttonActivityMain1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (buttonActivityMain1.getText().toString() == "鏈接"){ new Thread(new Runnable() { @Override public void run() { //這裏面寫具體的程序 try { socket = new Socket(editTextActivityMain1.getText().toString(),Integer.valueOf(editTextActivityMain2.getText().toString()));//鏈接TCP服務器 if (socket.isConnected()){//若是鏈接上TCP服務器 Log.e("MainActivity", "isConnected"); Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 1;//設置消息變量的 what 變量值 爲1 myHandler.sendMessage(msg);//插入消息隊列 outputStream = socket.getOutputStream();//獲取輸出數據流 inputStream = socket.getInputStream();//獲取輸入數據流 TcpClientReceive();//加載接收函數 } } catch (Exception e){ Log.e("MainActivity", e.toString()); } } }).start(); } else { try{ socket.close(); }catch (Exception e){} //關閉鏈接 try{ inputStream.close(); }catch (Exception e){} //關閉數據流 buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接 } } }); //發送按鈕 buttonActivityMain2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try{ //獲取發送數據框裏面的數據 if (checkBoxActivityMain2.isChecked()){//16進制發送 byte[] TcpSendData1 = HexString2Bytes(editTextActivityMain3.getText().toString().replace(" ", "")); TcpSendDataLen = TcpSendData1.length; TcpSendData = TcpSendData1; } else{ byte[] TcpSendData2 = editTextActivityMain3.getText().toString().replace(" ", "").getBytes("utf-8");//"gb2312","gbk","us-ascii" TcpSendDataLen = TcpSendData2.length; TcpSendData = TcpSendData2; } if (socket!=null && socket.isConnected()){//若是TCP是正常鏈接的 new Thread(new Runnable() { @Override public void run() { try{ outputStream.write(TcpSendData,0,TcpSendDataLen);//發送數據 }catch (Exception e){} } }).start(); } }catch (Exception e){} } }); } //TCP客戶端接收數據 public void TcpClientReceive(){ new Thread(new Runnable() { @Override public void run() { while(socket.isConnected()){//若是客戶端一直鏈接着就一直在任務裏面 try{ int TcpReceiveDataLen = inputStream.read(TcpReceiveData);//接收數據,服務器斷開會返回-1 if(TcpReceiveDataLen!=-1){ byte[] Buffer = new byte[TcpReceiveDataLen];//建立一個新的數組 System.arraycopy(TcpReceiveData, 0, Buffer, 0, TcpReceiveDataLen);//拷貝數據 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 2;//設置消息變量 msg.obj = Buffer;//obj 能夠接收任意類型的變量 myHandler.sendMessage(msg);//插入消息隊列 } else{//斷開了鏈接 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 9;//設置消息變量 myHandler.sendMessage(msg);//插入消息隊列 break; } }catch (Exception e){//接收數據有錯誤 Message msg = myHandler.obtainMessage();//從消息隊列拉取個消息變量 msg.what = 9;//設置消息變量 myHandler.sendMessage(msg);//插入消息隊列 break; } } } }).start(); } //Handler class MyHandler extends Handler { public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == 1){//接收到消息變量的 what 變量值 爲1 buttonActivityMain1.setText("斷開");//按鈕顯示斷開 } else if (msg.what == 2){//接收到消息變量的 what 變量值 爲2 try{ byte[] TcpReadData = (byte[])msg.obj;//接收消息 if (checkBoxActivityMain1.isChecked()){//選擇了顯示16進制 textViewActivityMain4.append(byteToHexStr(TcpReadData)); } else { textViewActivityMain4.append(new String(TcpReadData,"utf-8"));//追加顯示數據 "utf-8","gb2312","gbk","us-ascii" 參見:https://www.cnblogs.com/yangfengwu/p/10274289.html } //textViewActivityMain4.setText(new String(TcpReadData));//顯示一次數據從新刷新顯示 Log.e("MainActivity", new String(TcpReadData) );//打印消息 }catch (Exception e){} } else if (msg.what == 9){//接收到消息變量的 what 變量值 爲9 try{ socket.close(); }catch (Exception e){} //關閉鏈接 try{ inputStream.close(); }catch (Exception e){} //關閉鏈接 buttonActivityMain1.setText("鏈接");//按鈕顯示鏈接 Log.e("MainActivity", "和服務器斷開鏈接!!!" );//打印消息 } } } /** * 16進制byte轉16進制String--用空格隔開 * @param bytes * @return */ public static String byteToHexStr(byte[] bytes) { String str_msg = ""; for (int i = 0; i < bytes.length; i++){ str_msg = str_msg + String.format("%02X",bytes[i])+" "; } return str_msg; } /** * 將已十六進制編碼後的字符串src,以每兩個字符分割轉換爲16進制形式 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF, * 0xD9} * * @param src * String * @return byte[] */ public static byte[] HexString2Bytes(String str) { StringBuilder sb = null; String src = null; if ((str.length()%2)!=0) {//數據不是偶數 sb = new StringBuilder(str);//構造一個StringBuilder對象 sb.insert(str.length()-1, "0");//在指定的位置1,插入指定的字符串 src = sb.toString(); } else { src = str; } Log.e("error", "str.length()"+str.length()); byte[] ret = new byte[src.length() / 2]; byte[] tmp = src.getBytes(); for (int i = 0; i < tmp.length / 2; i++) { ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]); } return ret; } /** * 將兩個ASCII字符合成一個字節; 如:"EF"--> 0xEF * * @param src0 * byte * @param src1 * byte * @return byte */ public static byte uniteBytes(byte src0, byte src1) { try { byte _b0 = Byte.decode("0x"+new String(new byte[] { src0 })) .byteValue(); _b0 = (byte) (_b0 << 4); byte _b1 = Byte.decode("0x"+new String(new byte[] { src1 })) .byteValue(); byte ret = (byte) (_b0 ^ _b1); return ret; } catch (Exception e) { // TODO: handle exception } return 0; } }
測試