当前位置: 首页 > news >正文

Android Studio的笔记--socket通信

Android socket通信

  • Socket
  • 协议
  • android socket 代码
    • 清单文件
    • 开启服务
    • 服务端:TCPServerService
    • 客户端:TCPClientService
    • log

Socket

Socket 作为一种通用的技术规范,首次是由 Berkeley 大学在 1983 为 4.2BSD Unix 提供的,后来逐渐演化为 POSIX 标准。Socket API 是由操作系统提供的一个编程接口,让应用程序可以控制使用 socket 技术。
Socket API 不属于 TCP/IP协议簇,只是操作系统提供的一个是一个对 TCP / IP协议进行封装 的编程调用接口,工作在应用层与传输层之间:
一个 Socket 包含两个必要组成部分:
1地址:IP 和端口号组成一队套接字
2协议:Socket 所用的是传输层协议,目前有 TCP、UDP、raw IP

协议

根据传输方式不同(即使用的协议不同)可分为三种:
1.Stream Sockets(流套接字)
基于 TCP协议,采用 流的方式 提供可靠的字节流服务。TCP 协议有以下特点:
·面向连接:指的是要使用TCP传输数据,必须先建立TCP连接,传输完成后释放连接,就像打电话一样必须先拨号建立一条连接,打完后挂机释放连接。
·全双工通信:即一旦建立了TCP连接,通信双方可以在任何时候都能发送数据。
·可靠的:指的是通过TCP连接传送的数据,无差错,不丢失,不重复,并且按序到达。
·面向字节流:流,指的是流入到进程或从进程流出的字符序列。简单来说,虽然有时候要传输的数据流太大,TCP报文长度有限制,不能一次传输完,要把它分为好几个数据块,但是由于可靠性保证,接收方可以按顺序接收数据块然后重新组成分块之前的数据流,所以TCP看起来就像直接互相传输字节流一样,面向字节流。
2.Datagram Sockets(数据报套接字)
基于 UDP协议,采用 数据报文 提供数据打包发送的服务。UDP 协议有以下特点:
·无连接的:和TCP要建立连接不同,UDP传输数据不需要建立连接,就像写信,在信封写上收信人名称、地址就可以交给邮局发送了,至于能不能送到,就要看邮局的送信能力和送信过程的困难程度了。
·不可靠的:因为UDP发出去的数据包发出去就不管了,不管它会不会到达,所以很可能会出现丢包现象,使传输的数据出错。
·面向报文:数据报文,就相当于一个数据包,应用层交给UDP多大的数据包,UDP就照样发送,不会像TCP那样拆分。
·没有拥塞控制:拥塞,是指到达通信子网中某一部分的分组数量过多,使得该部分网络来不及处理,以致引起这部分乃至整个网络性能下降的现象,严重时甚至会导致网络通信业务陷入停顿,即出现死锁现象,就像交通堵塞一样。TCP建立连接后如果发送的数据因为信道质量的原因不能到达目的地,它会不断重发,有可能导致越来越塞,所以需要一个复杂的原理来控制拥塞。而UDP就没有这个烦恼,发出去就不管了。
3.Row Sockets
通常用在路由器或其他网络设备中,这种 socket 不经过TCP/IP协议簇中的传输层(transport layer),直接由网络层(Internet layer)通向应用层(Application layer),所以这时的数据包就不会包含 tcp 或 udp 头信息。

android socket 代码

清单文件

得添加权限 < uses-permission android:name=“android.permission.INTERNET” />

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.lxh.biji"android:installLocation="internalOnly"><uses-permission android:name="android.permission.INTERNET" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Shuiji"><activityandroid:name=".MainActivity"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><serviceandroid:name=".TCPServerService"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.newland.management.TCPServerService.and" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></service><serviceandroid:name=".TCPClientService"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.newland.management.TCPClientService.and" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></service></application>
</manifest>

开启服务

Intent intentx = new Intent("com.newland.management.TCPServerService.and");
intentx.setPackage("com.lxh.biji");
context.startService(intentx);
Intent intentx_ = new Intent("com.newland.management.TCPClientService.and");
intentx_.setPackage("com.lxh.biji");
context.startService(intentx_);

服务端:TCPServerService

package com.lxh.biji;
import android.app.IntentService;
import android.content.Intent;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/*** create by lxh on 2023/2/20 Time:16:33* tip:socket服务端 端口号55019,用来发送值*/
public class TCPServerService extends IntentService {private static final String TAG = "TCPServerService";public TCPServerService() {super("TCP");}@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "lxh "+TAG+"  onCreate: ");}@Overridepublic void onDestroy() {super.onDestroy();isover = true;Log.d(TAG, "lxh "+TAG+"  onDestroy: ");}private boolean isover = false;private String sendMag="";@Overrideprotected void onHandleIntent(@Nullable Intent intent) {try {Log.i(TAG,"lxh onHandleIntent");ServerSocket serverSocket = new ServerSocket(55019);//监听本地端口号Socket socket = serverSocket.accept();InputStream inputStream = socket.getInputStream();//获取输入流,接受用户发来的消息BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));OutputStream outputStream = socket.getOutputStream();//获取输出流,向客户端回复消息PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream));while (!isover) {//通过循环不断读取客户端发来的消息,并回复//Log.i(TAG,"lxh on while");String readLine = reader.readLine();if (!TextUtils.isEmpty(readLine)) {String readMag =readLine.toString();Log.i(TAG,"lxh 客户端发送的消息:"+readMag);if(readMag.equals("Client_send")){String need_String="Server_back";sendMag =need_String;}else if (readMag.equals("get")){ }//SystemClock.sleep(500);//延迟发送writer.println(sendMag+"\r");writer.flush();//刷新流}else { }}inputStream.close();//关闭流reader.close();outputStream.close();writer.close();socket.close();//需关闭,否则再次连接时,会报端口号已被使用serverSocket.close();} catch (IOException e) {e.printStackTrace();}}
}

客户端:TCPClientService

package com.lxh.biji;
import android.annotation.SuppressLint;
import android.app.IntentService;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
/*** create by lxh on 2023/2/20 Time:20:02* tip:socket客户端 端口号55019*/
public class TCPClientService extends IntentService {private static final String TAG = "TCPClientService";public TCPClientService() {super("TCP");}@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "lxh "+TAG+" onCreate: ");}@Overridepublic void onDestroy() {super.onDestroy();
//        isover_client = true;
//        //关闭输入流和连接
//        if (mSocket != null) {
//            try {
//                mSocket.shutdownInput();
//                mSocket.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }Log.d(TAG, "lxh "+TAG+" onDestroy: ");}private boolean isover_client = false;private String sendMag_client="";private static final int CONNECT_SERVER_SUCCESS = 0;private static final int MESSAGE_RECEIVE_SUCCESS = 1;private static final int MESSAGE_SEND_SUCCESS = 2;@Overrideprotected void onHandleIntent(@Nullable Intent intent) {new Thread(new Runnable() {@Overridepublic void run() {connectTCPServer();//连接服务端,实现通信交互//IO操作必须放在子线程执行}}).start();}Handler handler=new Handler();int handler_id=0;//handler.postDelayed(runnable, 2000);//handler.removeCallbacks(runnable);Runnable runnable=new Runnable() {@Overridepublic void run() {run_send();handler_id++;handler.postDelayed(this, 2000);if (handler_id>3){handler.removeCallbacks(runnable);//关闭输入流和连接if (mSocket != null) {try {mSocket.shutdownInput();mSocket.close();} catch (IOException e) {e.printStackTrace();}}}}};private void run_send(){new Thread(new Runnable() {@Overridepublic void run() {String msg = "Client_send";if (mPrintWriter != null && !TextUtils.isEmpty(msg)) {mPrintWriter.println(msg + "\n");//mPrintWriter.flush();//此处可以不用刷新流的方法,因为在创建mPrintWriter对象时,在其构造方法中设置了自动刷新缓存mHandler.obtainMessage(MESSAGE_SEND_SUCCESS, msg).sendToTarget();}}}).start();}private Socket mSocket = null;private void connectTCPServer() {while (mSocket == null) {//通过循环来判断Socket是否有被创建,若没有则会每隔1s尝试创建,目的是保证客户端与服务端能够连接try {mSocket = new Socket("localhost", 55019);//创建Socket对象,指定IP地址和端口号mPrintWriter = new PrintWriter(new OutputStreamWriter(mSocket.getOutputStream()), true);if (mSocket.isConnected()) //判断是否连接成功mHandler.sendEmptyMessage(CONNECT_SERVER_SUCCESS);} catch (IOException e) {e.printStackTrace();SystemClock.sleep(1000);//设计休眠机制,每次重试的间隔时间为1s}}try {BufferedReader reader = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));while (!isover_client) {//通过循环来,不断的接受服务端发来的消息String msg = reader.readLine();if (!TextUtils.isEmpty(msg)) {mHandler.obtainMessage(MESSAGE_RECEIVE_SUCCESS, msg).sendToTarget();}}mPrintWriter.close();//关闭流reader.close();} catch (IOException e) {e.printStackTrace();}}@SuppressLint("all")private Handler mHandler = new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {switch (msg.what) {case CONNECT_SERVER_SUCCESS:Log.i(TAG,"lxh 与服务端连接成功");//run_send();handler.postDelayed(runnable, 2000);break;case MESSAGE_RECEIVE_SUCCESS:Log.i(TAG,"lxh 服务端发来的消息:"+msg.obj.toString());break;case MESSAGE_SEND_SUCCESS://Log.i(TAG,"lxh 客户端发送的消息:"+msg.obj.toString());break;}return false;}});private PrintWriter mPrintWriter;
}

log

/com.lxh.biji D/TCPServerService: lxh TCPServerService  onCreate: 
/com.lxh.biji I/TCPServerService: lxh onHandleIntent
/com.lxh.biji D/TCPClientService: lxh TCPClientService onCreate: 
/com.lxh.biji D/TCPClientService: lxh TCPClientService onDestroy: 
/com.lxh.biji I/TCPClientService: lxh 与服务端连接成功
/com.lxh.biji I/TCPServerService: lxh 客户端发送的消息:Client_send
/com.lxh.biji I/TCPClientService: lxh 服务端发来的消息:Server_back
/com.lxh.biji I/TCPServerService: lxh 客户端发送的消息:Client_send
/com.lxh.biji I/TCPClientService: lxh 服务端发来的消息:Server_back
/com.lxh.biji I/TCPServerService: lxh 客户端发送的消息:Client_send
/com.lxh.biji I/TCPClientService: lxh 服务端发来的消息:Server_back

感谢互联网
引用内容来自Android Socket 通信
服务端部分代码参考Android进程间通信 - Socket使用(TCP、UDP)
适合阅读文章分享
Android 基于TCP的 Socket 编程实现(结合 okio)
Android实现socket网络通信
基于android的Socket通信

相关文章:

Android Studio的笔记--socket通信

Android socket通信Socket协议android socket 代码清单文件开启服务服务端&#xff1a;TCPServerService客户端&#xff1a;TCPClientServicelogSocket Socket 作为一种通用的技术规范&#xff0c;首次是由 Berkeley 大学在 1983 为 4.2BSD Unix 提供的&#xff0c;后来逐渐演化…...

@Async 注解

异步执行 异步调用就是不用等待结果的返回就执行后面的逻辑&#xff1b;同步调用则需要等待结果再执行后面的逻辑。 通常我们使用异步操作时都会创建一个线程执行一段逻辑&#xff0c;然后把这个线程丢到线程池中去执行&#xff0c;代码如下所示。 ExecutorService executor…...

Redis:缓存穿透、缓存雪崩和缓存击穿(未完待续)

Redis的缓存穿透、缓存雪崩和缓存击穿一. 缓存穿透1.1 概念1.2 造成的问题1.3 解决方案1.4 案例&#xff1a;查询商铺信息&#xff08;缓存穿透的实现&#xff09;二. 缓存雪崩2.1 概念2.2 解决方案三. 缓存击穿&#xff08;热点key&#xff09;3.1 概念3.2 解决方案3.3 案例&a…...

HIVE 基础(四)

目录 分桶&#xff08;Bucket&#xff09; 设定属性 定义分桶 案例 建表语句 表数据 上传到数据 创建分桶语句 加载数据 分桶抽样&#xff08;Sampling&#xff09; 随机抽样---整行数据 随机抽样---指定列 随机抽样---百分比 随机抽样---抽取行数 Hive视图&#…...

整型在内存中的存储(详细剖析大小端)——“C”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是整型在内存中的存储噢&#xff0c;现在&#xff0c;就让我们进入整型在内存中的存储的世界吧 数据类型详细介绍 整型在内存中的存储&#xff1a;原码、反码、补码 大小端字节序介绍及判断 数据类型介绍 前面我们已经学…...

PS_高低频和中性灰——双曲线

高低频 高低频磨皮&#xff1a;把皮肤分成两个图层&#xff0c;一层是纹理层也就是皮肤的毛孔。 一层是皮肤光滑层没有皮肤细节。 高频”图层为细节层&#xff0c;我们用图章工具修高频 “低频”图层为颜色层&#xff0c;我们用混合画笔修低频 原理&#xff1a;修颜色亮度光影…...

Vim 命令速查表

Vim 命令速查表 简介&#xff1a;Vim 命令速查表&#xff0c;注释化 vimrc 配置文件&#xff0c;经典 Vim 键盘图&#xff0c;实用 Vim 书籍&#xff0c;Markdown 格式&#xff0c;目录化检索&#xff0c;系统化学习&#xff0c;快速熟悉使用&#xff01; Vim 官网 | Vim | Vim…...

Java重要基本概念理解

熟悉JVM反射机制。 &#xff08;1&#xff09;反射的定义 Java反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法;对于任意一个对象&#xff0c;都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Ja…...

逆向工具之 unidbg 执行 so

1、unidbg 入门 unidbg 是一款基于 unicorn 和 dynarmic 的逆向工具&#xff0c; 可以直接调用 Android 和 IOS 的 so 文件&#xff0c;无论是黑盒调用 so 层算法&#xff0c;还是白盒 trace 输出 so 层寄存器值变化都是一把利器&#xff5e; 尤其是动态 trace 方面堪比 ida tr…...

zk-STARK/zk-SNARK中IP,PCP,IPCP,IOP,PIOP,LIP,LPCP模型介绍

我们的目标是构造 zkSNARK。在我们的目标场景中&#xff0c;Prover 只需要发送一个简短的证明字符串给 Verifier&#xff0c;而 Verifier 不需要给 Prover 发送任何消息。 直接构造一个满足这个场景的 zkSNARK 可能会很困难。一个更灵活的方式是在先在理想模型下构造证明系统&…...

StreamAPI

StreamAPI 最近开发用上了 Java8的StreamAPI,(咋现在才用?嗯哼,项目需要)自己也不怎么会,来总结一波吧! 别认为好抽象!!!干他就完事 一.StreamAPI介绍 就是用来处理集合的数据 其实到后面会发现和SQL的语句是差不多的~哈哈?你不信?往下面看 Stream:英文翻译叫做流 举个粟子…...

MySQl高可用集群搭建(MGR + ProxySQL + Keepalived)

前言 服务器规划&#xff08;CentOS7.x&#xff09; IP地址主机名部署角色192.168.x.101mysql01mysql192.168.x.102mysql02mysql192.168.x.103mysql03mysql192.168.x.104proxysql01proxysql、keepalived192.168.x.105proxysql02proxysql、keepalived 将安装包 mysql_cluster_…...

java+Selenium+TestNg搭建自动化测试架构(3)实现POM(page+Object+modal)

1.Page Object是Selenium自动化测试项目开发实践的最佳设计模式之一&#xff0c;通过对界面元素的封装减少冗余代码&#xff0c;同时在后期维护中&#xff0c;若元素定位发生变化&#xff0c;只需要调整页面元素封装的代码&#xff0c;提高测试用例的可维护性。 PageObject设计…...

oracle11g忘记system密码,重置密码

OPW-00001: 无法打开口令文件 cmd.exe 使用管理员身份登录 找到xxx\product\11.2.0\dbhome_1\database\PWDorcl.ora文件&#xff0c;删除 执行orapwd fileD:\app\product\11.2.0\dbhome_1\database\PWDorcl.ora passwordtiger (orapwd 在\product\11.2.0\dbhome_1\BIN目录下…...

黑马 Vue 快速入门 笔记

黑马 Vue 快速入门 笔记0 VUE相关了解0.1 概述0.2 MVVM0.3 JavaScript框架0.4 七大属性0.5 el:挂载点1 VUE基础1.0 第一个vue代码&#xff1a;Hello&#xff0c;vue1.1 v-bind 设置元素的属性 简写 &#xff1a;1.2 v-if &#xff0c; v-else &#xff0c; v-else-ifv-if , v-e…...

HTTP协议知识体系核心重点梳理

HTTP协议知识体系核心重点梳理TCP/IP协议1.四层模型2.通信过程3.tcp三次握手和四次挥手4.tcp安全传输4. 一次HTTP通信流程HTTP协议HTTP/1.1CookieHttp报文格式内容编码分块传输编码HTTP状态码重定向状态码常用的通用首部cache-controlExpiresConnectionTransfer-Encoding常用的…...

Nginx优化与防盗链

Nginx优化与防盗链 &#x1f4d2;博客主页&#xff1a; 微笑的段嘉许博客主页 &#x1f4bb;微信公众号&#xff1a;微笑的段嘉许 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐留言&#x1f4dd; &#x1f4cc;本文由微笑的段嘉许原创&#xff01; &#x1f4c…...

自动驾驶路径规划概况

文章目录前言介绍1. 路径规划在自动驾驶系统架构中的位置2. 全局路径规划的分类2.1 基础图搜索算法2.1.1 Dijkstra算法2.1.2 双向搜索算法2.1.3 Floyd算法2.2 启发式算法2.2.1 A*算法2.2.2 D*算法2.3 基于概率采样的算法2.3.1 概率路线图&#xff08;PRM&#xff09;2.3.2 快速…...

某某银行行面试题目汇总--HashMap为什么要扩容

一、HashMap啥时候扩容&#xff0c;为什么扩容&#xff1f; HashMap的默认大小是16。在实际开发过程中&#xff0c;我们需要去存储的数据量往往是大于存储容器的默认大小的。所以&#xff0c;出现容量默认大小不能满足需求时&#xff0c;就需要扩容。而这个扩容的动作是由集合自…...

求职者:“我有五年测试经验”面试官: “不,你只是把一年的工作经验用了五年”

最近看到很多软件测试由于公司裁员而需要重新求职的。他们普遍具有4年甚至更长的工作经验。但求职结果往往都不太理想。 我在与部分软件测试求职者交谈的过程中发现&#xff0c;很多人的工作思路不清晰&#xff0c;技能不扎实&#xff0c;没有持续学习的习惯&#xff0c;但对于…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...