对于DotNetEdge代理无法将BasicMessage发送到Aca-Py感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍edge无法连接到代理服务器,并为您提供关于activemq控制面板里
对于DotNet Edge 代理无法将 BasicMessage 发送到 Aca-Py感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍edge无法连接到代理服务器,并为您提供关于activemq 控制面板里的 Number Of Pending Messages、 Messages Enqueued、Messages Dequeued含、com.google.protobuf.GeneratedMessage.ExtendableMessage的实例源码、DotNetty 使用ByteToMessageDecoder 国家部标808协议封装、e.getMessage()和e.getLocalizedMessage()之间的区别的有用信息。
本文目录一览:- DotNet Edge 代理无法将 BasicMessage 发送到 Aca-Py(edge无法连接到代理服务器)
- activemq 控制面板里的 Number Of Pending Messages、 Messages Enqueued、Messages Dequeued含
- com.google.protobuf.GeneratedMessage.ExtendableMessage的实例源码
- DotNetty 使用ByteToMessageDecoder 国家部标808协议封装
- e.getMessage()和e.getLocalizedMessage()之间的区别
DotNet Edge 代理无法将 BasicMessage 发送到 Aca-Py(edge无法连接到代理服务器)
如何解决DotNet Edge 代理无法将 BasicMessage 发送到 Aca-Py?
我正在尝试使用以下代码将 Basicmessage
从 Xamarin Edge Agent 发送到 Aca-Py Cloud Agent
Hyperledger.Aries.Features.Basicmessage.Basicmessage basicmessage = new()
{
Content = "Some Text",SentTime = DateTime.UtcNow.ToString("s",CultureInfo.InvariantCulture)
};
IMessageService messageService = App.Container.Resolve<IMessageService>();
await messageService.SendAsync(AgentContext,basicmessage,Connection.Record);
Aca-Py 端没有收到消息
我也尝试发送如下消息。但是,我收到的错误是 {"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/notification/1.0/problem-report","@id": "8b605a23-b58d-466d-bb7a-eb456bd48ac1","~thread": {"thid": "59134bfd-7b2a-49ee-ac42-9a4c310c632b"},"explain-ltxt": "Error deserializing message: Basicmessage schema validation Failed"}
MessageContext messageContext = await messageService.SendReceiveAsync(AgentContext,Connection.Record);
未使用 Edge 代理上的以下代码获取 BasicmessageRecords,表明消息未从 Edge Agent 发送到 Aca-Py
List<BasicmessageRecord> basicmessageRecords = await walletRecordService.SearchAsync<BasicmessageRecord>(AgentContext.Wallet,SearchQuery.Equal(nameof(BasicmessageRecord.ConnectionId),ConnectionRecord.Id),null,int.MaxValue);
注意:Xamarin Edge Agent 能够毫无问题地接收来自 Aca-Py 的消息
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)
activemq 控制面板里的 Number Of Pending Messages、 Messages Enqueued、Messages Dequeued含
Number Of Consumers 消费者 这个是消费者端的消费者数量
Number Of Pending Messages 等待消费的消息 这个是当前未出队列的数量。可以理解为总接收数-总出队列数
Messages Enqueued 进入队列的消息 进入队列的总数量,包括出队列的。 这个数量只增不减
Messages Dequeued 出了队列的消息 可以理解为是消费这消费掉的数量
这个要分两种情况理解
在queues里它和进入队列的总数量相等(因为一个消息只会被成功消费一次),如果暂时不等是因为消费者还没来得及消费。
在 topics里 它因为多消费者从而导致数量会比入队列数高。
简单的理解上面的意思就是
当有一个消息进入这个队列时,等待消费的消息是1,进入队列的消息是1。
当消息消费后,等待消费的消息是0,进入队列的消息是1,出队列的消息是1.
在来一条消息时,等待消费的消息是1,进入队列的消息就是2.
没有消费者时 Pending Messages 和 入队列数量一样
有消费者消费的时候 Pedding会减少 出队列会增加
到最后 就是 入队列和出队列的数量一样多
以此类推,进入队列的消息和出队列的消息是池子,等待消费的消息是水流。
com.google.protobuf.GeneratedMessage.ExtendableMessage的实例源码
private <MType extends ExtendableMessage<MType>,BType extends ExtendableBuilder<MType,BType>> boolean resolveUninterpretedOptions( final BType optionsBuilder,final FieldDescriptor uninterpretedField) { ensureRegistry(); boolean anyUninterpetedOptionResolved = false; @SuppressWarnings("unchecked") final List<UninterpretedOption> options = new ArrayList<UninterpretedOption>( (List<UninterpretedOption>) optionsBuilder.getField(uninterpretedField)); for (final Iterator<UninterpretedOption> iterator = options.iterator(); iterator.hasNext();) { final UninterpretedOption option = iterator.next(); if (resolveUninterpretedOption(option,optionsBuilder)) { anyUninterpetedOptionResolved = true; iterator.remove(); } } if (options.isEmpty()) { optionsBuilder.clearField(uninterpretedField); } else { optionsBuilder.setField(uninterpretedField,options); } return anyUninterpetedOptionResolved; }
private <MType extends ExtendableMessage<MType>,BType>> boolean resolveUninterpretedOption( final UninterpretedOptionorBuilder option,final BType optionsBuilder) { if (option.getNameCount() == 0) { throw new IllegalArgumentException("custom option cannot be empty"); } if (!option.getName(0).getIsExtension()) { throw new IllegalArgumentException("custom option name should start with '('"); } final Map.Entry<FieldDescriptor,Object> fieldValue; if (option.getNameCount() == 1) { fieldValue = processUninterpretedOptionValue(option,optionsBuilder); } else { fieldValue = processUninterpretedOptionMessage(option,optionsBuilder); } if (fieldValue == null) { return false; } final FieldDescriptor field = fieldValue.getKey(); final Object value = fieldValue.getValue(); if (field == null || value == null) { // the UninterpretedOption is not resolved return false; } if (field.isRepeated()) { optionsBuilder.addRepeatedField(field,value); } else { optionsBuilder.setField(field,value); } return true; }
private <MType extends ExtendableMessage<MType>,BType>> boolean buildOptions( final BType optionsBuilder) { final FieldDescriptor uninterpretedField = getFD(optionsBuilder,UNINTERPRETED_OPTION_FIELD_NUMBER); final boolean isUninterpretedEmpty = optionsBuilder.getRepeatedFieldCount(uninterpretedField) == 0; final boolean anyUninterpetedOptionResolved = !isUninterpretedEmpty && resolveUninterpretedOptions(optionsBuilder,uninterpretedField); final boolean isUnkNownFieldsEmpty = optionsBuilder.getUnkNownFields().asMap().isEmpty(); Map<FieldDescriptor,Object> allFields = null; if (isUninterpretedEmpty && isUnkNownFieldsEmpty) { allFields = optionsBuilder.getAllFields(); if (allFields.isEmpty()) { return false; } } if (customOptionsAsExtensions) { if (!isUnkNownFieldsEmpty) { reparseBuilder(optionsBuilder,ensureRegistry()); } } else { boolean anyExtension = anyUninterpetedOptionResolved; if (!anyUninterpetedOptionResolved) { if (allFields == null) { allFields = optionsBuilder.getAllFields(); } for (final FieldDescriptor fd : allFields.keySet()) { if (fd.isExtension()) { anyExtension = true; break; } } } if (anyExtension) { reparseBuilder(optionsBuilder,ExtensionRegistry.getEmptyRegistry()); } } return true; }
DotNetty 使用ByteToMessageDecoder 国家部标808协议封装
DotNetty 开源地址 https://github.com/Azure/DotNetty
个人博客地址 http://www.dncblogs.cn/Blog/ShowBlog/70
1.国家部标808协议格式
标识位
采用 0x7e 表示,若校验码、消息头以及消息体中出现 0x7e,则要进行转义处理,转义
规则定义如下:
0x7e <————> 0x7d 后紧跟一个 0x02;
0x7d <————> 0x7d 后紧跟一个 0x01。
转义处理过程如下:
发送消息时:消息封装——>计算并填充校验码——>转义;
接收消息时:转义还原——>验证校验码——>解析消息。
示例:
发送一包内容为 0x30 0x7e 0x08 0x7d 0x55 的数据包,则经过封装如下:0x7e 0x30 7d 0x02 0x08 0x7d0x01 0x55 0x7
2.建立一个控制台程序
添加NuGet包
System.Text.Encoding.CodePages
Microsoft.Extensions.Configuration.CommandLine
Microsoft.Extensions.Configuration.EnvironmentVariables
Microsoft.Extensions.Configuration.Json
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging.Console
3.dotnetty 通道配置,使用默认的DelimiterBasedFrameDecoder 看看是否能够实现分包
bootstrap.Option(ChannelOption.SoBacklog, 100).Handler(new LoggingHandler("SRV-LSTN"))
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
pipeline.AddLast(new LoggingHandler("SRV-CONN"));
pipeline.AddLast("framing-dec", new DelimiterBasedFrameDecoder(1024, false, LineDelimiter()));
pipeline.AddLast("ServerClientHandler", new DBServerClientHandler());
}));
public static IByteBuffer[] LineDelimiter()
{
return new[]
{
Unpooled.WrappedBuffer(new[] { (byte)0x7e, (byte)0x7e }),
Unpooled.WrappedBuffer(new[] { (byte)0x7e }),
};
}
用网络调试工具 发送数据 7E 81 00 00 03 01 82 40 55 60 49 00 00 00 01 04 38 7E ,发现服务器收到数据后,分包数据错误了(一包数据编程2包数据了,数据格式也不对),
更改下分隔符代码,也出现一样的结果
public static IByteBuffer[] LineDelimiter()
{
return new[]
{
Unpooled.WrappedBuffer(new[] { (byte)0x7e }),
Unpooled.WrappedBuffer(new[] { (byte)0x7e }),
};
}
public static IByteBuffer[] LineDelimiter()
{
return new[]
{
Unpooled.WrappedBuffer(new[] { (byte)0x7e}),
};
}
4.使用ByteToMessageDecoder,代码如下
/// <summary>
///粘包处理 数据包 头和尾 标志 都包含分割 字符串
/// </summary>
public class BeiDouFrameDecoder : ByteToMessageDecoder
{
private int frameFlag = 0x7e;
private int manFrameLength;
private int minFrameLength;
private int delimiters = 2;
private IByteBuffer frameDelimiter;
/// <summary>
///
/// </summary>
/// <param name="frameFlag">数据包 标志</param>
/// <param name="maxFrameLength">数据包最大长度</param>
/// <param name="minFrameLength">数据包最小长度</param>
public BeiDouFrameDecoder(byte frameFlag, int maxFrameLength, int minFrameLength)
{
this.frameFlag = frameFlag;
this.manFrameLength = maxFrameLength;
this.minFrameLength = minFrameLength;
frameDelimiter = Unpooled.WrappedBuffer(new[] { frameFlag });
}
protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output)
{
if (input.ReadableBytes <= minFrameLength)//还不够 最小帧的 数据
return;
int readLen = -1;
//标记
int OriginalReadIndex = input.ReaderIndex;
input.MarkReaderIndex();
if (frameFlag == input.GetByte(OriginalReadIndex))//找到头 第一个字节是头 不改变 ReaderIndex
{
input.SetReaderIndex(OriginalReadIndex + 1);
readLen = IndexOfEnd(input);
input.ResetReaderIndex();
if (readLen != -1)//没有找到尾
{
readLen += delimiters;
if (readLen > manFrameLength || readLen < minFrameLength)
{
input.SkipBytes(readLen);
}
else
{
IByteBuffer frame = input.ReadSlice(readLen);
frame.Retain();
output.Add(frame);
}
}
}
else
{
//找头
int readIndex = -1;
int seekReaderIndex = input.ReaderIndex + 1;
while (seekReaderIndex < input.WriterIndex)
{
if (frameFlag == input.GetByte(seekReaderIndex))//找到头部
{
readIndex = seekReaderIndex;
break;
}
seekReaderIndex++;
}
if (readIndex != -1)//找到头
{
if ((input.ReadableBytes - readIndex) < minFrameLength)//可以读取的 数据长度小于最小帧长度,说明还不够一包数据,等下一次再读取
{
input.ResetReaderIndex();//本次跳过 还原ReaderIndex
return;
}
input.SetReaderIndex(readIndex + 1);
readLen = IndexOfEnd(input);
if (readLen == -1)//没有找打 尾
{
input.SkipBytes(input.ReadableBytes);//本次跳过 后面的所有字节
}
else if (readLen > manFrameLength || readLen < minFrameLength)//找到帧 但是长度 小于 最小长度 是错误的帧 SkipBytes
{
input.SetReaderIndex(readIndex);
input.SkipBytes(readLen + delimiters);
}
else
{
input.SetReaderIndex(readIndex);
IByteBuffer frame = input.ReadSlice(readLen + delimiters);
frame.Retain();
output.Add(frame);
}
}
}
}
private int IndexOfEnd(IByteBuffer haystack)
{
for (int i = haystack.ReaderIndex; i < haystack.WriterIndex; i++)
{
if (haystack.GetByte(i) != frameFlag)
{
continue;
}
else
{
if (i == haystack.WriterIndex)
{
return -1;
}
}
//Found the needle from the haystack! 找到
return i - haystack.ReaderIndex;
}
return -1;
}
//private static int IndexOf(IByteBuffer haystack, IByteBuffer needle)
//{
// for (int i = haystack.ReaderIndex; i < haystack.WriterIndex; i++)
// {
// int haystackIndex = i;
// int needleIndex;
// for (needleIndex = 0; needleIndex < needle.Capacity; needleIndex++)
// {
// if (haystack.GetByte(haystackIndex) != needle.GetByte(needleIndex))
// {
// break;
// }
// else
// {
// haystackIndex++;
// if (haystackIndex == haystack.WriterIndex && needleIndex != needle.Capacity - 1)
// {
// return -1;
// }
// }
// }
// if (needleIndex == needle.Capacity)
// {
// // Found the needle from the haystack!
// return i - haystack.ReaderIndex;
// }
// }
// return -1;
//}
}
修改通道代码
bootstrap.Option(ChannelOption.SoBacklog, 100).Handler(new LoggingHandler("SRV-LSTN"))
.ChildHandler(new ActionChannelInitializer<IChannel>(channel =>
{
IChannelPipeline pipeline = channel.Pipeline;
pipeline.AddLast(new LoggingHandler("SRV-CONN"));
pipeline.AddLast("BeiDouFrameDecoder", new BeiDouFrameDecoder(0x7e, 2048, 12));
pipeline.AddLast("ServerClientHandler", new DBServerClientHandler());
}));
测试结果
水平有限,欢迎指正。谢谢。
e.getMessage()和e.getLocalizedMessage()之间的区别
如何解决e.getMessage()和e.getLocalizedMessage()之间的区别?
就像上面每个人都提到的
据我了解,getMessage()
返回异常的名称。getLocalizedMessage()
以用户的本地语言(中文,日语等)返回异常的名称。为了使此工作正常,您正在调用的类getLocalizedMessage()
必须已重写该getLocalizedMessage()
方法。如果没有,则调用其中一个超类的方法,默认情况下,该方法仅返回getMessage的结果。
除此之外,我想放置一些代码段来解释如何使用它。
Java并没有提供任何神奇的功能,但是它确实提供了一种使我们的生活更轻松的方法。为了getLocalizedMessage()
有效使用,我们必须覆盖默认行为。
import java.util.ResourceBundle;
public class MyLocalizedThrowable extends Throwable {
ResourceBundle labels = ResourceBundle.getBundle("loc.exc.test.message");
private static final long serialVersionUID = 1L;
public MyLocalizedThrowable(String messageKey) {
super(messageKey);
}
public String getLocalizedMessage() {
return labels.getString(getMessage());
}
}
java.util.ResourceBundle
用于进行本地化。
在此示例中,您必须在loc/exc/test
路径中放置特定于语言的属性文件。例如:
message_fr.properties(包含一些键和值):
key1=this is key one in France
message.properties(包含一些键和值):
key1=this is key one in English
现在,让我们假设我们的异常生成器类类似于
public class ExceptionGenerator {
public void generateException() throws MyLocalizedThrowable {
throw new MyLocalizedThrowable("key1");
}
}
主要类别是:
public static void main(String[] args) {
//Locale.setDefault(Locale.FRANCE);
ExceptionGenerator eg = new ExceptionGenerator();
try {
eg.generateException();
} catch (MyLocalizedThrowable e) {
System.out.println(e.getLocalizedMessage());
}
}
默认情况下,如果您在“英语”环境中执行,它将返回“英语”键值。如果将本地设置为法国,则将从message_fr文件获取输出。
如果您的应用程序需要支持l10n / i18n,则需要使用它。但是大多数应用程序并不需要,因为大多数错误消息不是针对最终客户的,而是针对支持工程师/开发工程师的。
解决方法
- 我在执行错误处理时同时使用这两种方法来获取catch块抛出的消息
- 他们俩都从错误处理中得到了我的消息,但是两者的区别到底是什么
- 我从互联网上搜索了一些内容,然后从这里想出了这个答案
Java异常从Throwable继承其getMessage和getLocalizedMessage方法(请参见相关链接)。区别在于子类应重写getLocalizedMessage以提供特定于语言环境的消息。例如,想象一下您正在将代码从一个说英语的公司/组改编为一个英语-
英语组。您可能需要创建自定义Exception类,该类将覆盖getLocalizedMessage,以将拼写和语法正确化为将使用您的代码的用户和开发人员所期望的内容。这也可以用于异常消息的实际翻译。
问题 ::
-
这意味着
language specific
实现吗?就像如果我使用e.getLocalizedMessage()
我的应用程序English
-错误将被抛出English
,如果我使用我的应用程序Spanish
-那么错误将被抛出Spanish
-
需要在何时何地可以使用这些方法的清楚说明
关于DotNet Edge 代理无法将 BasicMessage 发送到 Aca-Py和edge无法连接到代理服务器的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于activemq 控制面板里的 Number Of Pending Messages、 Messages Enqueued、Messages Dequeued含、com.google.protobuf.GeneratedMessage.ExtendableMessage的实例源码、DotNetty 使用ByteToMessageDecoder 国家部标808协议封装、e.getMessage()和e.getLocalizedMessage()之间的区别的相关信息,请在本站寻找。
本文标签: