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[];//用来缓存接收的数据
@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 = ;//设置消息变量的 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!=-){
byte[] Buffer = new byte[TcpReceiveDataLen];//创建一个新的数组
System.arraycopy(TcpReceiveData, , Buffer, , TcpReceiveDataLen);//拷贝数据
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
msg.obj = Buffer;//obj 可以接收任意类型的变量
myHandler.sendMessage(msg);//插入消息队列
}
else{//断开了连接
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
myHandler.sendMessage(msg);//插入消息队列
}
}catch (Exception e){//接收数据有错误
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
myHandler.sendMessage(msg);//插入消息队列
}
}
}
}).start();
} //Handler
class MyHandler extends Handler {
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == ){//接收到消息变量的 what 变量值 为1
buttonActivityMain1.setText("断开");//按钮显示断开
}
else if (msg.what == ){//接收到消息变量的 what 变量值 为2
try{
byte[] TcpReadData = (byte[])msg.obj;//接收消息
Log.e("MainActivity", new String(TcpReadData) );//打印消息
}catch (Exception e){} }
else if (msg.what == ){//接收到消息变量的 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[];//用来缓存接收的数据
@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 = ;//设置消息变量的 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!=-){
byte[] Buffer = new byte[TcpReceiveDataLen];//创建一个新的数组
System.arraycopy(TcpReceiveData, , Buffer, , TcpReceiveDataLen);//拷贝数据
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
msg.obj = Buffer;//obj 可以接收任意类型的变量
myHandler.sendMessage(msg);//插入消息队列
}
else{//断开了连接
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
myHandler.sendMessage(msg);//插入消息队列
break;
}
}catch (Exception e){//接收数据有错误
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
myHandler.sendMessage(msg);//插入消息队列
break;
}
}
}
}).start();
} //Handler
class MyHandler extends Handler {
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == ){//接收到消息变量的 what 变量值 为1
buttonActivityMain1.setText("断开");//按钮显示断开
}
else if (msg.what == ){//接收到消息变量的 what 变量值 为2
try{
byte[] TcpReadData = (byte[])msg.obj;//接收消息
Log.e("MainActivity", new String(TcpReadData) );//打印消息
}catch (Exception e){} }
else if (msg.what == ){//接收到消息变量的 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 = ; 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()%)!=) {//数据不是偶数
sb = new StringBuilder(str);//构造一个StringBuilder对象
sb.insert(str.length()-, "");//在指定的位置1,插入指定的字符串
src = sb.toString();
}
else {
src = str;
}
Log.e("error", "str.length()"+str.length());
byte[] ret = new byte[src.length() / ];
byte[] tmp = src.getBytes();
for (int i = ; i < tmp.length / ; i++)
{
ret[i] = uniteBytes(tmp[i * ], tmp[i * + ]);
}
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 << );
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 ;
}

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[];//用来缓存接收的数据
byte[] TcpSendData = new byte[];//用来缓存发送的数据
int TcpSendDataLen =;//发送的数据个数
@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 = ;//设置消息变量的 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,,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!=-){
byte[] Buffer = new byte[TcpReceiveDataLen];//创建一个新的数组
System.arraycopy(TcpReceiveData, , Buffer, , TcpReceiveDataLen);//拷贝数据
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
msg.obj = Buffer;//obj 可以接收任意类型的变量
myHandler.sendMessage(msg);//插入消息队列
}
else{//断开了连接
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
myHandler.sendMessage(msg);//插入消息队列
break;
}
}catch (Exception e){//接收数据有错误
Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
msg.what = ;//设置消息变量
myHandler.sendMessage(msg);//插入消息队列
break;
}
}
}
}).start();
} //Handler
class MyHandler extends Handler {
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == ){//接收到消息变量的 what 变量值 为1
buttonActivityMain1.setText("断开");//按钮显示断开
}
else if (msg.what == ){//接收到消息变量的 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 == ){//接收到消息变量的 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 = ; 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()%)!=) {//数据不是偶数
sb = new StringBuilder(str);//构造一个StringBuilder对象
sb.insert(str.length()-, "");//在指定的位置1,插入指定的字符串
src = sb.toString();
}
else {
src = str;
}
Log.e("error", "str.length()"+str.length());
byte[] ret = new byte[src.length() / ];
byte[] tmp = src.getBytes();
for (int i = ; i < tmp.length / ; i++)
{
ret[i] = uniteBytes(tmp[i * ], tmp[i * + ]);
}
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 << );
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 ;
}
}

测试

23-ESP8266 SDK开发基础入门篇--编写Android TCP客户端 , 加入消息处理的更多相关文章

  1. 22-ESP8266 SDK开发基础入门篇--编写Android TCP客户端 , 连接和断开

    https://www.cnblogs.com/yangfengwu/p/11192618.html 有些很细致的东西参考这篇   https://www.cnblogs.com/yangfengwu ...

  2. 27-ESP8266 SDK开发基础入门篇--编写Android SmartConfig一键配网程序

    style="font-size: 18pt;">https://www.cnblogs.com/yangfengwu/p/11429007.html https://wik ...

  3. 29-ESP8266 SDK开发基础入门篇--编写TCP 客户端程序(Lwip RAW模式,非RTOS版,精简入门)

    https://www.cnblogs.com/yangfengwu/p/11456667.html 由于上一节的源码长时间以后会自动断开,所以再做这一版非RTOS版的,咱直接用lua源码里面别人写的 ...

  4. 28-ESP8266 SDK开发基础入门篇--编写wifi模块TCP 客户端程序(官方API版,非RTOS版)

    https://www.cnblogs.com/yangfengwu/p/11432795.html 注:这节实现的功能是WIFI模块作为TCP 客户端,连接咱的TCP服务器,然后实现透传 本来想着做 ...

  5. 26-ESP8266 SDK开发基础入门篇--编写WIFI模块 SmartConfig/Airkiss 一键配网

    https://www.cnblogs.com/yangfengwu/p/11427504.html SmartConfig/Airkiss 配网需要APP/微信公众号,这节大家先使用我做好的APP/ ...

  6. 8-ESP8266 SDK开发基础入门篇--编写串口上位机软件

    https://www.cnblogs.com/yangfengwu/p/11087558.html 咱用这个编写 ,版本都无所谓哈,只要自己有就可以,不同版本怎么打开 https://www.cnb ...

  7. 9-ESP8266 SDK开发基础入门篇--编写串口上位机软件

    https://www.cnblogs.com/yangfengwu/p/11087613.html 页面修改成这样子             现在看串口发送数据 点击点亮 发送0xaa 0x55 0 ...

  8. 19-ESP8266 SDK开发基础入门篇--C# TCP客户端编写 , 连接和断开

    https://www.cnblogs.com/yangfengwu/p/11130428.html 渐渐的看过去,,,好多节了... 这节做一个C# TCP客户端 新建项目啥子的就不详细截图写了,自 ...

  9. 1-ESP8266 SDK开发基础入门篇--开发环境搭建

    因为今天终于做好了自己的另一块工控板,所以我就开始写基础公开篇的内容,希望自己小小的努力能够帮到大家 自己做的另一块板子 https://www.cnblogs.com/yangfengwu/cate ...

随机推荐

  1. 《JAVA高并发编程详解》-程序可能出现死锁的场景

  2. Linux学习笔记之tail命令显示最后n行

    tail :输出文件的最后几行. 用于linux查看日志的时候很方便,假如日志文件为:Console.log用法:1. tail Console.log tail # 输出文件最后10行的内容 2. ...

  3. 切换GCC编译器版本

    当前版本信息 root@ubuntu:runninglinuxkernel_4.0# aarch64-linux-gnu-gcc -v Using built-in specs. COLLECT_GC ...

  4. IE浏览器 location.href 不跳转

    var url = "https://www.cnblogs.com/zing"; location.href = url; window.event.returnValue = ...

  5. PropTypes.element和PropTypes.node的区别

    PropTypes.element:指React Element,即React.CreateElement生成的元素,React.CreateElement可以用jsx语法糖表示: <MyBut ...

  6. CSS-宽度自适应和浏览器兼容笔记

    自适应 宽度自适应:网页元素根据窗口或子元素自动调整宽度 适用百分比进行设置,例如:100% 铺满:50% 占据一般宽度 块元素如果不设置宽度,默认为100% 自适应中可以设置最大或者最小宽度和高度 ...

  7. golang之reflection

    反射就是程序能够在运行时检查变量和值,求出它们的类型. reflect包实现运行时反射. 创建一个接收任何数据类型任何数值的查询string: func createQuery(q interface ...

  8. docker容器监控:cadvisor+influxdb+grafana

    cadvisor+influxdb+grafana可以实现容器信息获取.存储.显示等容器监控功能,是目前流行的docker监控开源方案. 方案介绍 cadvisor Google开源的用于监控基础设施 ...

  9. Seata 动态配置订阅与降级实现原理

    Seata 的动态降级需要结合配置中心的动态配置订阅功能.动态配置订阅,即通过配置中心监听订阅,根据需要读取已更新的缓存值,ZK.Apollo.Nacos 等第三方配置中心都有现成的监听器可实现动态刷 ...

  10. mysql where 1

    where后跟各种查询条件,当条件为真时即可查询出记录.在这里where 1,1为真,也就是where后的条件为真,查询表中所有内容. SELECT * FROM `sdb_pam_members` ...