https://www.cnblogs.com/yangfengwu/p/11203546.html
先做接收消息
然后接着
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 接收数据
测试服务器突然故障
稍等,,我还是直接打印一下日志比较好
................有BUG
加上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; } }
测试