GEE处理哨兵数据并导出

https://code.earthengine.google.com/dc35e6894b8d75711ca0ec449edc0f73


// 定义研究区域和样本数据
var roi = ee.FeatureCollection('users/messi513112/xiamen2');
var samples = ee.FeatureCollection('users/messi513112/Expor_xiament_point'); // 替换为您的shapefile文件的实际路径

//导入sentinel-1和sentinel-2的图像集合
var s1 = ee.ImageCollection('COPERNICUS/S1_GRD');
var s2 = ee.ImageCollection('COPERNICUS/S2_SR');
// 获取NASA数据
var nasaDEM = ee.Image('NASA/NASADEM_HGT/001').clip(roi);


//重采样
var scale = 10;
// 重采样Sentinel-1影像集
var resampledS1 = s1.map(function(image) {
  return image.resample('bilinear').reproject({
    crs: image.select(0).projection().crs(),
    scale: scale
  });
});

// 重采样Sentinel-2影像集
var resampledS2 = s2.map(function(image) {
  return image.resample('bilinear').reproject({
    crs: image.select(0).projection().crs(),
    scale: scale
  });
});

// 重采样NASA DEM数据
var resampledDEM = nasaDEM.resample('bilinear').reproject({
  crs: nasaDEM.projection().crs(),
  scale: scale
});





// 定义时间范围
var start = ee.Date('2018-01-01');
var end = ee.Date('2018-12-31');

// 计算属性 'YSSZ_S' 中每个值的数量。
var valueCounts = samples.aggregate_histogram('YSSZ_S');
// 打印结果。
print(valueCounts);

// 使用简单的云和云影掩膜
function maskS2clouds(image) {
  var qa = image.select('QA60');

  // Bits 10和11是云和阴影的标识符
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // 两个标志应设置为零,表示云和云影的清除
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask).divide(10000);
}


//纹理特征
var vh = resampledS1
  .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VV'))
  .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VH'))
  .filter(ee.Filter.eq('instrumentMode', 'IW'))
 .map(function(image) {
          var edge = image.lt(-30.0);
          var maskedImage = image.mask().and(edge.not());
          return image.updateMask(maskedImage).clip(roi);
        });
// 筛选不同观测角度的图像
var vhAscending = vh.filter(ee.Filter.eq('orbitProperties_pass', 'ASCENDING'));
var vhDescending = vh.filter(ee.Filter.eq('orbitProperties_pass', 'DESCENDING'));
var spring = ee.Filter.date('2018-01-01', '2018-12-31');
// 从不同极化和观测角度的平均值创建合成图像
var composite = ee.Image.cat([
  ee.ImageCollection(vhAscending.select('VH').merge(vhDescending.select('VH'))).filter(spring).mean(),
  ee.ImageCollection(vhAscending.select('VV').merge(vhDescending.select('VV'))).filter(spring).mean(),
]).focal_median();
print('composite',composite);
// 作为极化和后向散射特性的合成显示
Map.addLayer(composite, {min: -20, max: 0}, 'composite');
// 计算纹理特征
var glcm = composite.multiply(100).toInt().glcmTexture({
    'size': 1,
    'kernel': null
});

// 打印纹理特征
print('GLCM:', glcm);

glcm =glcm.select(['VH_asm',
                   'VH_contrast',
                   'VH_corr',
                   'VH_var',
                   'VH_idm',
                   'VH_savg',
                   'VH_sent',
                   'VH_ent',
                   'VH_dvar',
                   'VH_dent',
                   'VH_imcorr1',
                   'VH_imcorr2',
                   'VH_diss',
                   'VH_inertia',
                   'VH_shade',
                   'VH_prom',
                   //'VV_asm',
                   //'VV_contrast',
                  // 'VV_corr',
                   //'VV_var',
                   //'VV_idm',
                   //'VV_savg',
                   //'VV_sent',
                   //'VV_ent',
                   //'VV_dvar',
                   //'VV_dent',
                   //'VV_imcorr1',
                   //'VV_imcorr2',
                   //'VV_diss',
                   //'VV_inertia',
                   //'VV_shade',
                   //'VV_prom',
                    ]);



// 筛选Sentinel-2数据
var s2filtered = resampledS2
  .filterBounds(roi)
  .filterDate(start, end)
  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 40));
// 应用去云函数到筛选后的影像集
var s2CloudRemoved = s2filtered.map(maskS2clouds);
// 打印筛选后的Sentinel-2数据集的元数据,以检查数据集
print('Sentinel-2 filtered metadata:', s2CloudRemoved);
//多时相合成
var s2composite = s2CloudRemoved
  .median() // 多时相合成,这里使用中位数
  .clip(roi); // 裁剪到研究区域
// 显示Sentinel-2多时相合成的结果
Map.addLayer(s2composite, {min: 0, max: 3000, bands: ['B4', 'B3', 'B2']}, 'Sentinel-2 Composite', false);
//提取Sentinel-2的光谱特征
var spectral = s2composite.select(['B4', 'B5', 'B6', 'B7', 'B8']);



// 定义一个函数来计算 NDVI
function addNDVI(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI');
  return ndvi;
}

// 定义一个函数来计算 EVI
function addEVI(image) {
  var evi = image.expression(
    '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', {
      'NIR': image.select('B8'),
      'RED': image.select('B4'),
      'BLUE': image.select('B2')
    }).rename('EVI');
  return evi;
}

// 定义一个函数来计算 NDWI
function addNDWI(image) {
  var ndwi = image.normalizedDifference(['B3', 'B8']).rename('NDWI');
  return ndwi;
}

// 定义一个函数来计算 NDRE
function addNDRE(image) {
  var ndre = image.normalizedDifference(['B8', 'B5']).rename('NDRE');
  return ndre;
}

// 定义一个函数来计算 SAVI
function addSAVI(image) {
  var savi = image.expression(
    '((NIR - RED) / (NIR + RED + L)) * (1 + L)', {
      'NIR': image.select('B8'),
      'RED': image.select('B4'),
      'L': 0.5
    }).rename('SAVI');
  return savi;
}

// 定义一个函数来计算 MSAVI
function addMSAVI(image) {
  var msavi = image.expression(
    '(2 * NIR + 1 - sqrt((2 * NIR + 1)**2 - 8 * (NIR - RED))) / 2', {
      'NIR': image.select('B8'),
      'RED': image.select('B4')
    }).rename('MSAVI');
  return msavi;
}

// 定义一个函数来计算 ARVI
function addARVI(image) {
  var arvi = image.expression(
    '(NIR - (2 * RED - BLUE)) / (NIR + (2 * RED - BLUE))', {
      'NIR': image.select('B8'),
      'RED': image.select('B4'),
      'BLUE': image.select('B2')
    }).rename('ARVI');
  return arvi;
}




// 应用函数并显示结果
var NDVI = addNDVI(s2composite);
var EVI = addEVI(s2composite);
var NDWI = addNDWI(s2composite);
var NDRE = addNDRE(s2composite);
var SAVI = addSAVI(s2composite);
var MSAVI = addMSAVI(s2composite);
var ARVI = addARVI(s2composite);

// 生长季开始(SOS)
var sos = NDVI.reduce(ee.Reducer.firstNonNull());

// 生长季结束(EOS)
var eos = NDVI.reduce(ee.Reducer.lastNonNull());

// 初花期
var startOfFlowering = NDVI.reduce(ee.Reducer.first().setOutputs(['StartOfFlowering']));

// 叶变色期
var endOfSenescence = NDVI.reduce(ee.Reducer.last().setOutputs(['EndOfSenescence']));

// 准备Sentinel-2数据
var ss2 = ee.ImageCollection('COPERNICUS/S2')
          .filterDate('2018-01-01', '2018-12-31') // 根据设置的时间范围过滤影像
          .filterBounds(roi) // 根据定义的区域过滤影像
          .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 40)) // 过滤云量小于40%的影像
          .map(function(image) {
            // 计算NDVI并将其作为一个波段添加
            var ndvi = image.normalizedDifference(['B8', 'B4']).rename('NDVI');
            // 将system:time_start属性转换为图像并重命名为'time'
            var time = ee.Image.constant(image.get('system:time_start')).toFloat().rename('time');
            // 返回包含NDVI和时间波段的图像
            return ndvi.addBands(time);
          });

// 对ImageCollection应用linearFit reducer
var linearFit = ss2.select(['NDVI', 'time']).reduce(ee.Reducer.linearFit());



// 计算地形特征
var terrain = ee.Algorithms.Terrain(resampledDEM);

// 提取地形特征波段
var elevation = terrain.select('elevation'); // 海拔
var slope = terrain.select('slope'); // 坡度
var aspect = terrain.select('aspect'); // 坡向
var hillshade = terrain.select('hillshade'); // 山体阴影



var img1 = ee.ImageCollection('COPERNICUS/S2')
    .filterDate('2018-2-13', '2018-2-14')
    .filterBounds(roi)
    .median();
  
var img6 = ee.ImageCollection('COPERNICUS/S2')
    .filterDate('2018-9-26', '2018-9-27')
    .filterBounds(roi)
    .median();

// 计算SVI
var svi = img1.addBands(img6)
            .rename(['B4_1', 'B8_1', 'B4_6', 'B8_6'])
            .expression(
              '((1/6) * timeDiff * (LB8 - LB4) * (B4_1 + 2 * B8_1 + 2 * B4_6 + B8_6))/100000', {
                'timeDiff': 225,
                //'centralWavelengths': centralWavelengths,
                'B4_1': img1.select('B4'),
                'B8_1': img1.select('B8'),
                'B4_6': img6.select('B4'),
                'B8_6': img6.select('B8'),
                'LB8':835.1,
                'LB4':664.5
              }
            ).rename('SVI');
            
// 计算B3与B8之间的SVI
var sviB3B8 = img1.addBands(img6)
  .rename(['B3_1', 'B8_1', 'B3_6', 'B8_6'])
  .expression(
    '(((1/6) * timeDiff * (835.1 - 560.0) * (B3_1 + 2 * B8_1 + 2 * B3_6 + B8_6))/10000)-6800', {
      'timeDiff': 225,
      'B3_1': img1.select('B3'),
      'B8_1': img1.select('B8'),
      'B3_6': img6.select('B3'),
      'B8_6': img6.select('B8')
    }
  ).rename('SVI_B3_B8');

// 计算B5与B8之间的SVI
var sviB5B8 = img1.addBands(img6)
  .rename(['B5_1', 'B8_1', 'B5_6', 'B8_6'])
  .expression(
    '((1/6) * timeDiff * (835.1 - 703.9) * (B5_1 + 2 * B8_1 + 2 * B5_6 + B8_6))/10000-2700', {
      'timeDiff': 225,
      'B5_1': img1.select('B5'),
      'B8_1': img1.select('B8'),
      'B5_6': img6.select('B5'),
      'B8_6': img6.select('B8')
    }
  ).rename('SVI_B5_B8');

// 计算B6与B8之间的SVI
var sviB6B8 = img1.addBands(img6)
  .rename(['B6_1', 'B8_1', 'B6_6', 'B8_6'])
  .expression(
    '((1/6) * timeDiff * (835.1 - 740.2) * (B6_1 + 2 * B8_1 + 2 * B6_6 + B8_6))/10000-2700', {
      'timeDiff': 225,
      'B6_1': img1.select('B6'),
      'B8_1': img1.select('B8'),
      'B6_6': img6.select('B6'),
      'B8_6': img6.select('B8')
    }
  ).rename('SVI_B6_B8');

// 计算B7与B8之间的SVI
var sviB7B8 = img1.addBands(img6)
  .rename(['B7_1', 'B8_1', 'B7_6', 'B8_6'])
  .expression(
    '((1/6) * timeDiff * (835.1 - 782.5) * (B7_1 + 2 * B8_1 + 2 * B7_6 + B8_6))/10000-1000', {
      'timeDiff': 225,
      'B7_1': img1.select('B7'),
      'B8_1': img1.select('B8'),
      'B7_6': img6.select('B7'),
      'B8_6': img6.select('B8')
    }
  ).rename('SVI_B7_B8');

// 计算B8A与B8之间的SVI
var sviB8AB8 = img1.addBands(img6)
  .rename(['B8A_1', 'B8_1', 'B8A_6', 'B8_6'])
  .expression(
    '((1/6) * timeDiff * (864.8 - 835.1) * (B8A_1 + 2 * B8_1 + 2 * B8A_6 + B8_6))/10000', {
      'timeDiff': 225,
      'B8A_1': img1.select('B8A'),
      'B8_1': img1.select('B8'),
      'B8A_6': img6.select('B8A'),
      'B8_6': img6.select('B8')
    }
  ).rename('SVI_B8A_B8');

// 特征融合 想导出的特征
var features = glcm//.addBands(spectral)
                   .addBands(NDVI)
                   .addBands(EVI)
                   //.addBands(NDWI)
                   //.addBands(NDRE)
                   //.addBands(SAVI)
                   //.addBands(MSAVI)
                   //.addBands(ARVI)
                   //.addBands(sos)
                   //.addBands(eos)
                   //.addBands(startOfFlowering)
                   //.addBands(endOfSenescence)
                   //.addBands(linearFit)
                   //.addBands(elevation)
                   //.addBands(slope)
                   //.addBands(aspect)
                   //.addBands(hillshade)
                   .addBands(svi)
                   //.addBands(sviB3B8)
                   //.addBands(sviB5B8)
                   //.addBands(sviB6B8)
                   //.addBands(sviB7B8)
                   //.addBands(sviB8AB8);
                   
                   
print(features);

// 假设'image'是您要导出的影像
var imageToExport = features.toFloat(); // 将所有波段转换为Float32类型

// 定义导出参数
var exportParams = {
  image: imageToExport,
  description: 'export_image',
  scale: 10,
  region: roi, // 确保已定义导出区域的几何形状
  maxPixels: 1e13
};

// 开始导出图像
Export.image.toDrive(exportParams);


// 定义您想要保留的样本数量。
var numSamples =200;
// 从特征集合中随机选择样本。
var randomSamples = samples.randomColumn('random').sort('random').limit(numSamples);
print(randomSamples);

// 训练数据准备
var training = features.sampleRegions({
  collection: randomSamples,
  properties: ['YSSZ_S'],
  scale: 10,
  tileScale:16
})


// 打印训练数据集,以检查样本和特征
print('Training data:', training);
// 随机化样本数据集并添加随机列
var samplesWithRandom = training.randomColumn('random');
// 设置训练和验证样本的比例
var split = 0.5; 
var trainingPartition = samplesWithRandom.filter(ee.Filter.lt('random', split));
var testingPartition = samplesWithRandom.filter(ee.Filter.gte('random', split));
// 训练随机森林分类器
var classifier = ee.Classifier.smileRandomForest(50).train({
  features: trainingPartition,
  classProperty: 'YSSZ_S',
  inputProperties: features.bandNames()
});
print(classifier.explain()); 
// 对整个区域进行分类
var classified = features.classify(classifier);

// 获取分类结果的特征集
var classifiedFeatures = ee.FeatureCollection(classified);

// 使用验证样本集评估模型性能
var test = testingPartition.classify(classifier);
// 计算混淆矩阵
var confusionMatrix = test.errorMatrix('YSSZ_S', 'classification');
// 打印混淆矩阵和精度评估指标
print('Confusion Matrix:', confusionMatrix);
print('Overall Accuracy:', confusionMatrix.accuracy());
print('Kappa Accuracy:', confusionMatrix.kappa());

// 定义一个颜色列表,每个类别一个颜色
var palette = [
  'ffd966', // 浅黄色,代表针叶林
  '8db360', // 橄榄绿,代表落叶阔叶林
  '006400', // 深绿色,代表常绿阔叶林
  'ffbb22', // 金色,代表混交林
  'f13c20', // 天蓝色,代表红树林
  '92cddc'  // 地红色,代表灌木丛
];
// 添加分类结果的图层到地图上
Map.addLayer(classified, {min: 1, max: 8, palette: palette}, 'Classification Result');

// 导出分类结果
Export.image.toDrive({
  image: classified,
  description: 'xiamen_classification',
  folder: 'xiamen_classification',
  scale: 10,
  region: roi,
  maxPixels: 1e13
});

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二、OSPF协议基础

基于SPF算法&#xff08;Dijkstra算法&#xff09;的链路状态路由协议OSPF&#xff08;Open Shortest Path First&#xff0c;开放式最短路径优先&#xff09; 目录 1.RIP在大型网络中部署所面临的问题 2.Router ID 3.OSPF的报文 4.OSPF邻居建立过程 5.OSPF报文的确认机制…

59、回溯-括号生成

思路&#xff1a; 括号是成对出现&#xff0c;首先左括号可以放n个&#xff0c;右括号也可以放n个。如果当前左括号放了3了&#xff0c;右括号放了4个&#xff0c;错了&#xff0c;如果左括号放了5个&#xff0c;右括号放了4个。可以&#xff0c;继续放右括号即可。所以可以设…

linux系统安全及应用【上】

目录 1.账号安全控制 1系统账号清理 2密码安全控制 1 对已经存在的用户账号进行控制 2 对新建的用户密码默认设置 3 历史命令和终端自动注销的安全管理 1 历史命令的限制 2. 用户切换管理 1 su命令的使用 2 ssh 3.授权用户管理 1 sudo命令 2 sudo用户别名 3 查看su…

Vuforia AR篇(三)— AR模型出场效果

目录 前言一、AR模型出场二、AR出场特效三、添加过渡效果四、效果 前言 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0c;很多人都开启了学习机器学习&#xff0c;本文就介绍了机器学习的基础内容。 一、AR模型出场 创建ARCamer…

【Go语言快速上手(四)】面向对象的三大特性引入

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Go语言专栏⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Go语言知识   &#x1f51d;&#x1f51d; GO快速上手 1. 前言2. 初识GO中的结构…

深度学习中的子空间、线性变换和矩阵概念应用

1.表示子空间 在深度学习中&#xff0c;“不同的表示子空间”通常是指模型通过不同的参数&#xff08;例如权重矩阵&#xff09;将输入数据映射到不同的高维空间&#xff0c;这些空间被称为表示子空间。每个子空间都能够捕获输入数据中不同的特征或模式。以下是一些详细解释&am…

软考-论文写作-论架构风格论文

题目 素材 框架 一、 摘要 2020年12月,我参加了某省政协委员履职系统的开发。该系统为政协机关人员线上开展各项工作以及委员完成各项履职提供了全方位的软件支撑。我在该项目重担任系统架构师一职,负责履职系统的架构设计。本文结合实践,以委员履职系统为例,主要讨论软件…

使用FunASR处理语音识别

FunASR是阿里的一个语音识别工具&#xff0c;比SpeechRecognition功能多安装也很简单&#xff1b; 官方介绍&#xff1a;FunASR是一个基础语音识别工具包&#xff0c;提供多种功能&#xff0c;包括语音识别&#xff08;ASR&#xff09;、语音端点检测&#xff08;VAD&#xff…

verilog中比较器的代码用法

在 verilog 中以大于“>”&#xff0c;等于””&#xff0c;小于”<”&#xff0c;大于等于”>”&#xff0c;小于等于”<”&#xff0c;不等于”!”表示&#xff0c;以大于举例&#xff0c;如 c a > b ;表示如果 a 大于 b&#xff0c;那么 c 的值就为 1&#x…

网盘——文件重命名

文件重命名具体步骤如下&#xff1a; 目录 1、具体步骤 2、代码实现 2.1、添加重命名文件的槽函数 2.2、关联重命名文件夹信号槽 2.3、添加重命名文件的协议 2.4、添加槽函数定义 2.5、服务器 2.6、添加重命名文件的case 2.7、客户端接收回复 3、测试 3.1、点击重命…

【AIGC调研系列】Bunny-Llama-3-8B-V与其他多模态大模型相比的优劣

Bunny-Llama-3-8B-V作为基于Llama-3的多模态大模型&#xff0c;其优势主要体现在以下几个方面&#xff1a; 性能超越其他模型&#xff1a;根据我搜索到的资料&#xff0c;Bunny-Llama-3-8B-V在多个主流Benchmark上表现良好&#xff0c;超越了LLaVA-7B、LLaVA-13B、Mini-Gemini…

汽车企业安全上网解决方案

需求背景 成立于1866年的某老牌汽车服务独立运营商&#xff0c;目前已经是全球最大的独立汽车服务网络之一&#xff0c;拥有95年的历史&#xff0c;在全球150多个国家拥有17,000多个维修站&#xff0c;始终致力于为每一位车主提供高品质&#xff0c;可信赖的的专业汽车保养和维…

智慧文旅:引领旅游产业智慧升级的创新模式

一、智慧文旅是什么&#xff1f; 智慧文旅是指以当地特色文化为核心&#xff0c;借助现代科技手段&#xff0c;实现旅游景区全面智慧升级的旅游模式。在智慧文旅中&#xff0c;新一代信息网络技术和装备得到充分运用&#xff0c;文化旅游基础设施得到新建和改善&#xff0c;特…

OpenCV鼠标绘制线段

鼠标绘制线段 // 鼠标回调函数 void draw_circle(int event, int x, int y, int flags, void* param) {cv::Mat* img (cv::Mat*)param;if (event cv::EVENT_LBUTTONDBLCLK){cv::circle(*img, cv::Point(x, y), 100, cv::Scalar(0, 0, 255), -1);} }// 鼠标回调函数 void dra…

牛客NC199 字符串解码【中等 递归,栈的思想 C++/Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/4e008fd863bb4681b54fb438bb859b92 相同题目&#xff1a; https://www.lintcode.com/problem/575 思路 解法和基础计算器1&#xff0c;2,3类似,递归参考答案C struct Info {string str;int stopindex;Info(str…

react —— useState 深入

基础用法 useState Hook 提供了这两个功能&#xff1a; State 变量 在第一次重新渲染期间&#xff0c;这将具有作为参数传递的值State setter 函数 set 函数将允许将状态的值更新为不同的值&#xff0c;如果 set 函数中提供的值不同&#xff0c;则将触发重新渲染。 注意&…

【网站项目】书籍销售系统小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

如何3分钟,快速开发一个新功能

背景 关于为什么做这个代码生成器&#xff0c;其实主要有两点: 参与的项目中有很多分析报表需要展示给业务部门&#xff0c;公司使用的商用产品&#xff0c;或多或少有些问题&#xff0c;这部分可能是历史选型导致的&#xff0c;这里撇开不不谈&#xff1b;项目里面也有很多C…

torch.cuda.is_avaliable()在命令行里是true,pycharm是false【省流:换Pycharm】

我的问题&#xff1a; 1、torch.cuda.is_avaliable()在命令行里是true&#xff0c;但是pycharm是false 2、pycharm选择pytorch所在的解释器&#xff0c;加载失败。 3、pytorch所在的解释器加载成功&#xff0c;但是里边的torch包莫名消失。 解决方法&#xff1a; 在调试了很…

SpringBoot+RabbitMQ实现MQTT协议通讯

一、简介 MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上&#xff0c;是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议&#xff0c;为此&#xff0c;它需要一个消息中间件 。此…
最新文章