• Android 开发: 通信篇-TCP客户端


    说明

    这节教给大家用Android写一个TCP客户端程序

    官方文档

    https://www.android-doc.com/reference/java/net/Socket.html

    页面

    编写连接程序

    1.获取控件

        EditText editTextIPAddress,editTextPort;//输入IP地址,端口号
        Button buttonConnect;//连接按钮
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            buttonConnect = findViewById(R.id.buttonConnect);
            editTextIPAddress = findViewById(R.id.editTextIPAddress);
            editTextPort = findViewById(R.id.editTextPort);
    
    
        }

    2.添加网络权限

    <uses-permission android:name="android.permission.INTERNET" />

    3.定义一个socket

    Socket socket;

    4.编写按钮点击连接/断开程序

    MyHandler myHandler;//使用Handler更新控件
    
    myHandler = new MyHandler();

            buttonConnect.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (buttonConnect.getText()=="连接"){
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                                try{
                                    socket = new Socket(editTextIPAddress.getText().toString(),Integer.valueOf(editTextPort.getText().toString()));
                                    if(socket.isConnected()){
                                        msg.what = 1;//设置消息变量的 what 变量值 为1
                                    }
                                }catch (Exception e){
                                    msg.what = 0;//设置消息变量的 what 变量值 为0
                                }
                                myHandler.sendMessage(msg);//插入消息队列
                            }
                        }).start();
                    }
                    else{
                        try{ socket.close(); }catch (Exception e){} //关闭连接
                        buttonConnect.setText("连接");//按钮显示连接
                    }
                }
            });

    //Handler
        class MyHandler extends Handler {
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what){
                    case 0:
                        Toast.makeText(MainActivity.this,"连接出错",Toast.LENGTH_SHORT).show();
                        break;
                    case 1:
                        buttonConnect.setText("断开");//按钮显示断开
                        break;
                    default: break;
                }
            }
        }

    提示:获取IP地址和端口号,执行连接

    socket = new Socket(editTextIPAddress.getText().toString(),Integer.valueOf(editTextPort.getText().toString()));

    当前程序

        EditText editTextIPAddress,editTextPort;//输入IP地址,端口号
        Button buttonConnect;//连接按钮
        Socket socket;
    
        MyHandler myHandler;//使用Handler更新控件
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            myHandler = new MyHandler();
            buttonConnect = findViewById(R.id.buttonConnect);
            buttonConnect.setText("连接");
            editTextIPAddress = findViewById(R.id.editTextIPAddress);
            editTextPort = findViewById(R.id.editTextPort);
    
            buttonConnect.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (buttonConnect.getText()=="连接"){
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                                try{
                                    socket = new Socket(editTextIPAddress.getText().toString(),Integer.valueOf(editTextPort.getText().toString()));
                                    if(socket.isConnected()){
                                        msg.what = 1;//设置消息变量的 what 变量值 为1
                                    }
                                }catch (Exception e){
                                    msg.what = 0;//设置消息变量的 what 变量值 为0
                                }
                                myHandler.sendMessage(msg);//插入消息队列
                            }
                        }).start();
                    }
                    else{
                        try{ socket.close(); }catch (Exception e){} //关闭连接
                        buttonConnect.setText("连接");//按钮显示连接
                    }
                }
            });
        }
    
        //Handler
        class MyHandler extends Handler {
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what){
                    case 0:
                        Toast.makeText(MainActivity.this,"连接出错",Toast.LENGTH_SHORT).show();
                        break;
                    case 1:
                        buttonConnect.setText("断开");//按钮显示断开
                        break;
                    default: break;
                }
            }
        }

    接收数据

    1.定义 InputStream 用于获取数据输入流,定义一个数组用于缓存数据

        InputStream inputStream;//获取输入流
        byte[] RevBuff = new byte[1460];//缓存数据

    2.定义一个函数,里面放一个任务,用于不停的接收数据

     

    public void Recv(){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (socket!= null && socket.isConnected()){
                        try{
                            int Len = inputStream.read(RevBuff);//获取数据
                            if(Len!=-1){
                                Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                                msg.what = 3;//设置消息变量的 what 变量值 为3
                                msg.arg1 = Len;//接收的数据个数
                                msg.obj = RevBuff;//传递数据
                                myHandler.sendMessage(msg);//插入消息队列
                            }
                            else{//连接异常断开
                                Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                                msg.what = 0;//设置消息变量的 what 变量值 为0
                                myHandler.sendMessage(msg);//插入消息队列
                                break;
                            }
                        }catch (Exception e){//连接异常断开
                            Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                            msg.what = 0;//设置消息变量的 what 变量值 为0
                            myHandler.sendMessage(msg);//插入消息队列
                            break;
                        }
                    }
                }
            }).start();
        }

     

     

    3.调用接收函数

    4.在Handle中处理数据,把数据显示在页面

    4.1.获取控件

    4.2.把接收的消息追加到Textview显示

    测试

    1.电脑端开启TCP服务器

    2.保证手机和电脑在一个局域网内

    查看自己的电脑IP

    3.手机连接

    接收显示16进制数据

    1.关于16进制显示和前面的串口上位机显示16进制数据是一样的道理

    https://www.cnblogs.com/yangfengwu/p/12382103.html

    2.JAVA和C#提供的函数不一样,java的转换程序如下:

        /**
         * 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;    
        }  

    3.获取16进制选择控件

    4.编写处理函数

     

    测试

    清除接收

    发送数据

    1.获取控件,定义输出流变量

    2.获取输出流

    3.点击发送按钮发送发送文本框里面的数据

    4.测试

    发送16进制数据

    1.文本框里面输入的是字符串

    假设输入的是 55FD

    那么获取的是 "55FD"

    需要转换为 0x55  0xFD

    获取第一个字符 5    hexString.charAt(0)

    转换为 16进制形式  Character.digit(hexString.charAt(0), 16)

    获取第二个字符5     hexString.charAt(1)

    转换为 16进制形式  Character.digit(hexString.charAt(1), 16)

    然后组合成一个16进制

    byte data =  (byte) ((Character.digit(hexString.charAt(0), 16) << 4) + Character.digit(hexString.charAt(1), 16))

    2.完整的程序如下

    /***
         *"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF,0xD9}
         * @param hexString
         * @return
         */
        public static byte[] hexStringToByteArray(String hexString) {
            StringBuilder sb = null;
            hexString = hexString.replaceAll(" ", "");
    
            if ((hexString.length()%2)!=0) {//数据不是偶数
                sb = new StringBuilder(hexString);//构造一个StringBuilder对象
                sb.insert(hexString.length()-1, "0");//插入指定的字符串
                hexString = sb.toString();
            }
    
            int len = hexString.length();
            byte[] bytes = new byte[len / 2];
            for (int i = 0; i < len; i += 2) {
                if ((
                        (hexString.charAt(i)>='0' && hexString.charAt(i)<='9') ||
                        (hexString.charAt(i)>='A' && hexString.charAt(i)<='F') ||
                        (hexString.charAt(i)>='a' && hexString.charAt(i)<='f')
                 )&&
                        (hexString.charAt(i+1)>='0' && hexString.charAt(i+1)<='9') ||
                        (hexString.charAt(i+1)>='A' && hexString.charAt(i+1)<='F') ||
                        (hexString.charAt(i+1)>='a' && hexString.charAt(i+1)<='f')){
                    // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节
                    bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
                            .digit(hexString.charAt(i+1), 16));
                }
                else return null;
            }
            return bytes;
        }

    3.获取控件

    4.编写处理程序

    5.测试

    补充

    让输入的内容默认显示在左上角

    android:gravity="top"
  • 相关阅读:
    Thread中的join使用
    java.lang.NoClassDefFoundError: Ljavax/enterprise/inject/spi/BeanManager;
    org.hibernate.HibernateException: Could not parse configuration: /hibernate.cfg.xm
    maven 中使用jstl 错误解决
    eclipse 安装maven
    前端 JS事件操作
    前端 JS
    前端 固定位置 与绝对定位
    前端 显示与隐藏
    前端 盒子阴影
  • 原文地址:https://www.cnblogs.com/yangfengwu/p/12543923.html
Copyright © 2020-2023  润新知