Java中的TCP (Android通用)

news2024/11/29 9:36:15

TCP服务端,创建了一个线程的接口

 

public class TCPServer implements Runnable {
    private static final String TAG = "TCPServer";

    private String chaSet = "UTF-8";

    private int port;
    private boolean isListen = true;
    public TCPServer(int port) {
        this.port = port;
    }

    @Override
    public void run() {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            Log.d(TAG, "run:等待客户端连接... ");
            //serverSocket.setSoTimeout(2000);
            if (isListen) {
                Socket socket = serverSocket.accept();
                Log.d(TAG, "run: 客户端已连接");
                if (socket != null) {
                    accept(socket);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void accept(Socket socket) {
        InputStream is;
        OutputStream os;
        try {
            is = socket.getInputStream();
            os = socket.getOutputStream();
            int len;
            byte[] bytes = new byte[1024 * 4];

            while (!socket.isClosed() && !socket.isInputShutdown()) {
                while ((len = is.read(bytes)) != -1) {
                    Log.d(TAG, "accept: len: " + len);
                    byte[] content = new byte[bytes.length];
                    System.arraycopy(bytes, 0, content, 0, bytes.length);

                    String res = new String(content, chaSet);
                    String trim = res.trim(); //打印的时候去掉多余部分

                    if (onReceiveListener != null) {
                        onReceiveListener.receive(trim);
                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


   //创建回调  用于在主线程中监听收消息事件

    private onReceiveListener onReceiveListener;

    public interface onReceiveListener {
        void receive(String bytes);
    }

    public void setOnReceiveListener(onReceiveListener onReceiveListener) {
        this.onReceiveListener = onReceiveListener;
    }


}

在主线程中创建线程,调用接口回调监听:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TCPServer tcpServer=new TCPServer(9899);
        new Thread(tcpServer).start();
        tcpServer.setOnReceiveListener(new TCPServer.onReceiveListener() {
            @Override
            public void receive(String bytes) {
                Log.d(TAG, "receive: bytes: "+bytes);
            }
        });
    }
}

然后用网络调试助手给服务端发消息:

最后记得申请网络请求:

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

新增需求:定义所需要的数据结构接受数据。

根据定义好的数据结构的长度解析,接受到的bytes然后进行如下处理:

        int postX = 0;
        int postY = 0;
        int size = 0;
        int reserveOne = 0;
        int reserveTwo = 0;
        String reserve = "";
        int color = 0;
        long pngLen = 0L;

       postX = getInt(bytes, 0, 4);
       postY = getInt(bytes, 4, 4);
       size = getInt(bytes, 8, 4);
       reserveOne = getInt(bytes, 12, 4);
       reserveTwo = getInt(bytes, 16, 4);
       reserve = getString(bytes, 20, 56);
       color = getInt(bytes, 76, 4);
       pngLen = getInt(bytes, 80, 4);
       if (onReceiveListener != null) {
           onReceiveListener.receive(postX, postY, size, reserveOne, reserveTwo, reserve, color, pngLen);
                  


 //byte转int
    public int getInt(byte[] srcBytes, int srcPos, int length) {
        byte[] bytes = new byte[length];
        System.arraycopy(srcBytes, srcPos, bytes, 0, length);
        int anInt = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt();
        return anInt;
    }


    //byte转String
    public String getString(byte[] srcBytes, int srcPos, int length) {
        byte[] bytes = new byte[length];
        System.arraycopy(srcBytes, srcPos, bytes, 0, length);
        String str = "解析错误";
        try {
            str = new String(bytes, 0, length, chaSet);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str.trim();
    }


  

ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getInt() 方法的作用是将给定的字节数组 bytes 转换为一个整数值。

首先,ByteBuffer.wrap(bytes) 创建了一个新的字节缓冲区,并将其包装在给定的字节数组 bytes 上。这意味着后续的操作将在该缓冲区上进行。

接下来,.order(ByteOrder.LITTLE_ENDIAN) 设置字节缓冲区的字节顺序为小端序(Little Endian)。字节顺序决定了多字节数据类型在内存中的存储方式,小端序表示低位字节存储在内存的低地址处,高位字节存储在内存的高地址处。

最后,.getInt() 从字节缓冲区中读取四个字节,并将其解释为一个整数值。字节缓冲区的当前位置将被移动四个字节的长度,以便下一次读取操作。

大端小端是什么?询问了chatGPT

大端(Big Endian)和小端(Little Endian)是用于描述多字节数据在内存中的存储方式的两种字节序(byte order)。

在计算机中,多字节数据类型(例如整数、浮点数)通常由多个字节组成。这些字节按照一定的顺序在内存中存储。大端序和小端序指定了这些字节在内存中的排列方式。

  • 大端序(Big Endian):在大端序中,最高有效字节(Most Significant Byte,MSB)存储在最低的内存地址处,最低有效字节(Least Significant Byte,LSB)存储在最高的内存地址处。类似于数字书写习惯,高位字节在前,低位字节在后。

  • 小端序(Little Endian):在小端序中,最低有效字节(LSB)存储在最低的内存地址处,最高有效字节(MSB)存储在最高的内存地址处。与大端序相反,低位字节在前,高位字节在后。

下面是一个示例,用于说明大端序和小端序的区别:

假设有一个四字节的整数值 0x12345678(十六进制表示),它在内存中的存储如下:

  • 大端序:地址高位->低位

    高地址 12 | 34 | 56 | 78 低地址

  • 小端序:地址低位->高位

    低地址 78 | 56 | 34 | 12 高地址

需要注意的是,大端序和小端序仅在多字节数据类型的存储方面有所区别。对于单字节的数据类型(如字符),字节序没有影响,因为它们只有一个字节。字节序的选择在不同的体系结构和通信协议中具有重要的意义,特别是在跨平台或网络通信时,正确处理字节序是至关重要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/528293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TypeScript 学习笔记 (学习中)

学习视频1&#xff1a;coderwhy 学习视频2&#xff1a;尚硅谷 文章目录 TypeScript 学习笔记概述TypeScript 开发环境搭建 类型注解类型推断 数据类型JS的7个原始类型Array数组object、Object 和 {}1.可选属性 ? 2.type 类型别名 和 接口interface函数TS类型: any类型 | unkno…

分享Python采集66个css3代码,总有一款适合您

分享Python采集66个css3代码&#xff0c;总有一款适合您 Python采集的66个css3代码下链接&#xff1a; 百度网盘 请输入提取码 提取码&#xff1a;mads css3svg炫酷水滴Loading特效 css剪裁GIF背景图片动画特效 纯CSS制作辛普森一家卡通人物动画特效 CSS3图片遮罩层变形…

1688商品详情数据采集技术,支持整站数据高并发采集

一、如何通过手动方式查看1688商品详情页面的数据 1.1688商品详情 API 接口&#xff08;item_get - 获得1688商品详情接口&#xff09;&#xff0c;1688API 接口代码对接可以获取到宝贝 ID&#xff0c;宝贝标题&#xff0c;价格&#xff0c;优惠价&#xff0c;掌柜名称&a…

ArcSWAT报错:-2147217385;创建栅格数据集失败

文章目录 1 报错内容2 报错分析3 解决方案3.1 数据集路径错误3.2 数据格式不受支持3.3 文件访问权限问题 1 报错内容 此报错通常发生在建立了一个SWAT数据库后&#xff0c;执行Watershed Delineator中的Automatic Watershed Delineation操作中&#xff0c;在选择了DEM数据后弹出…

亚马逊云科技Amazon Compute Optimizer基础设施

亚马逊云科技Amazon Compute Optimizer如今推出了一项新功能&#xff0c;可以利用多个CPU架构&#xff08;包括基于x86的实例和基于Amazon Graviton的实例&#xff09;更轻松地优化EC2实例。Compute Optimizer是一项可选服务基础设施&#xff0c;可为工作负载推荐最佳Amazon资源…

Kali-linux使用OpenVAS

OpenVAS&#xff08;开放式漏洞评估系统&#xff09;是一个客户端/服务器架构&#xff0c;它常用来评估目标主机上的漏洞。OpenVAS是Nessus项目的一个分支&#xff0c;它提供的产品是完全地免费。OpenVAS默认安装在标准的Kali Linux上&#xff0c;本节将介绍配置及启动OpenVAS。…

Flink基础介绍-3 Time与Window

Flink基础介绍-3 Time与Window 三、流处理中的Time与Window3.1 Time3.2 window3.3 Window API3.4 Watermark 三、流处理中的Time与Window 3.1 Time Event Time&#xff1a;是事件创建的时间。它通常由事件中的时间戳描述&#xff0c;例如采集的日志数据中&#xff0c;每一条日…

SpringSecurity原理和实际应用

前提知识 认证&#xff1a;系统提供的用于识别用户身份的功能&#xff0c;通常提供用户名和密码进行登录其实就是在进行认证&#xff0c;认证的目的是让系统知道你是谁。 授权&#xff1a;用户认证成功后&#xff0c;需要为用户授权&#xff0c;其实就是指定当前用户可以操作哪…

Spring Resource接口 学习

Resource 接口是 Spring 资源访问策略的抽象&#xff0c;它本身并不提供任何资源访问实现&#xff0c;具体的资源访问由该接口的实现类完成——每个实现类代表一种资源访问策略。Resource一般包括这些实现类&#xff1a;UrlResource、ClassPathResource、FileSystemResource、S…

MySQL基础(三十二)事务基础知识

1 数据库事务概述 1.1 存储引擎支持情况 SHOW ENGINES 命令来查看当前 MySQL 支持的存储引擎都有哪些&#xff0c;以及这些存储引擎是否支持事务。 能看出在 MySQL 中&#xff0c;只有InnoDB 是支持事务的。 1.2 基本概念 事务&#xff1a;一组逻辑操作单元&#xff0c;使数…

由浅入深理解java集合(三)——集合 List

一、List集合 List集合判断元素相等的标准 List判断两个对象相等只要通过equals()方法比较返回true即可&#xff08;关于equals()方法的详解可以参考第二篇文章中的内容&#xff09;。 下面以用代码具体展示。 创建一个Book类&#xff0c;并重写equals()方法&#xff0c;如果两…

ctf.show MiSC入门 图片篇 (信息附加)

目录 图片篇 信息附加 misc5 misc6 misc7 misc8 misc9 misc10 misc11 misc12 misc13 misc14 misc15 misc16 misc17 misc18 misc19 misc20 misc 21 misc22 misc23 misc41 图片篇 信息附加 misc5 打开后啥也没有 使用16进制编辑器打开&#xff0c;在最下面…

就业内推 | 上市公司招网工运维,有华为、思科、华三认证均可

01 软通动力 &#x1f537;招聘岗位&#xff1a;网络工程师 &#x1f537;职责描述&#xff1a; 1、负责大型数据中心网络运维及变更&#xff0c;包括架构优化、性能调优、服务上线 2、负责网络故障类问题定位及排查&#xff0c;对于复杂故障类问题能够定位、跟进和解决实施等…

数据分析案例-BI工程师招聘岗位信息可视化分析(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

25.在vue中使用axios

目录 1 项目中安装 axios 2 做测试用的后端 3 全局引入axios 4 定义全局根路径 1 项目中安装 axios 2 做测试用的后端 我们用python的flask做后端 简单来讲就是&#xff0c;发两个数字&#xff0c;如果是get就两个数相加&#xff0c;如果是post就两个数相乘 3 全局引…

Kali-linux使用Nessus

Nessus号称是世界上最流行的漏洞扫描程序&#xff0c;全世界有超过75000个组织在使用它。该工具提供完整的电脑漏洞扫描服务&#xff0c;并随时更新其漏洞数据库。Nessus不同于传统的漏洞扫描软件&#xff0c;Nessus可同时在本机或远端上遥控&#xff0c;进行系统的漏洞分析扫描…

【数据结构初阶】——第八节.优先级队列(小根堆的模拟实现)

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;Java初阶数据结构 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 目录 …

API接口三问

一、API数据接口可以给我们带来哪些便利 API数据接口可以给我们带来以下便利&#xff1a; 数据共享&#xff1a;API允许数据在不同的应用程序之间共享。这使得数据转移更容易&#xff0c;因为不需要手动复制和粘贴数据内容。 程序集成&#xff1a;API作为中间件&#xff0c;可…

20年+资深审稿人:什么情况下建议文章大小修、拒稿或接收?

文章进入外审后&#xff0c;作者最终可能会得到大小修、接收或拒稿的意见。那么&#xff0c;审稿人是怎么给出这些不同意见的呢&#xff1f;有哪些方面需要作者提前了解呢&#xff1f; Surgery 发布过一篇文章&#xff0c;里面调查了一些具有20年审稿经验、平均年龄69岁的编委会…

ThreadLocal八股文

目录 1. 为什么要⽤ ThreadLocal? 2. ThreadLocal 的原理是什么&#xff1f; 3. 为什么⽤ ThreadLocal 做 key&#xff1f; 4. Entry 的 key 为什么设计成弱引⽤&#xff1f; 5. ThreadLocal 真的会导致内存泄露&#xff1f; 6. 如何解决内存泄露问题&#xff1f; 7. T…