热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

对ActiveMQ.NET1.1.0组件接受中文信息乱码的修复

最近在使用ApacheActiveMQ消息队列做一些工作,在使用的时候,发现发送消息的内容是中文时,获得消息时,获得的是乱码。发送和接收我使用的是ActiveMQ.NET1.1.0组件。

最近在使用 Apache ActiveMQ 消息队列做一些工作,在使用的时候,发现发送消息的内容是中文时,获得消息时,获得的是乱码。

发送和接收我使用的是 ActiveMQ .NET 1.1.0 组件。

分析原因进去后,发现是这个开源组件的 Apache.NMS.ActiveMQ 组件的 /Apache.NMS.ActiveMQ-1.1.0-src/src/main/csharp/Transport/Stomp/StompWireFormat.cs 文件对应的 StompWireFormat 类的 public Object Unmarshal(BinaryReader dis) 方法中有错误。

错误在该文件的 166 行

之前的错误代码如下:

public Object Unmarshal(BinaryReader dis)
{
string command;
do {
command = ReadLine(dis);
}
while (command == "");

Tracer.Debug("<<<" + command);

IDictionary headers = new Hashtable();
string line;
while ((line = ReadLine(dis)) != "")
{
int idx = line.IndexOf(':');
if (idx > 0)
{
string key = line.Substring(0, idx);
string value = line.Substring(idx + 1);
headers[key] = value;

Tracer.Debug("<<<" + key + " = " + value);
}
else
{
// lets ignore this bad header!
}
}
byte[] cOntent= null;
string length = ToString(headers["content-length"]);
if (length != null)
{
int size = Int32.Parse(length);
cOntent= dis.ReadBytes(size);
// Read the terminating NULL byte for this frame.
int nullByte = dis.Read();
if(nullByte != 0)
{
Tracer.Debug("<<<");
}
}
else
{
MemoryStream ms = new MemoryStream();
int nextChar;
while((nextChar = dis.Read()) != 0)
{
if( nextChar <0 )
{
// EOF ??
break;
}
ms.WriteByte((byte)nextChar);
}
cOntent= ms.ToArray();
}
Object answer = CreateCommand(command, headers, content);
Tracer.Debug("<<<" + answer);
return answer;
}

internal String ReadLine(BinaryReader dis)
{
MemoryStream ms = new MemoryStream();
while (true)
{
int nextChar = dis.Read();
if (nextChar <0)
{
throw new IOException("Peer closed the stream.");
}
if( nextChar == 10 )
{
break;
}
ms.WriteByte((byte)nextChar);
}
byte[] data = ms.ToArray();
return encoding.GetString(data, 0, data.Length);
}

这个源代码文件可以在下面地址看到:

https://svn.apache.org/repos/asf/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/tags/1.1.0/src/main/csharp/Transport/Stomp/StompWireFormat.cs

正确的代码如下:

internal string ReadLine(NetworkStream ns)
{
MemoryStream ms = new MemoryStream();
while (true)
{
int nextChar = ns.ReadByte();
if (nextChar <0)
{
throw new IOException("Peer closed the stream.");
}
if (nextChar == 10)
{
break;
}
ms.WriteByte((byte)nextChar);
}
byte[] data = ms.ToArray();
return encoding.GetString(data, 0, data.Length);
}
public Object Unmarshal(BinaryReader dis)
{
NetworkStream ns = dis.BaseStream as NetworkStream;
if (ns == null) return null;
if (!ns.CanRead) return null;

// 读取 command 信息
string command;
do
{
command = ReadLine(ns);
}
while (command == "");

Tracer.Debug("<<<" + command);

// 读取 header 信息
IDictionary headers = new Hashtable();
string line;
while ((line = ReadLine(ns)) != "")
{
int idx = line.IndexOf(':');
if (idx > 0)
{
string key = line.Substring(0, idx);
string value = line.Substring(idx + 1);
headers[key] = value;

Tracer.Debug("<<<" + key + " = " + value);
}
else
{
// lets ignore this bad header!
}
}

// 读取消息内容
MemoryStream ms = new MemoryStream();
do
{
int t = ns.ReadByte();
if (t <= 0) break;
ms.WriteByte((byte)t);
}
while (ns.DataAvailable);

byte[] cOntent= ms.ToArray();

Object answer = CreateCommand(command, headers, content);
Tracer.Debug("<<<" + answer);
return answer;
}

之前的错误代码,在发送“a1郭红俊b2” 这样的中英文数字混合的信息时,发送时,发送的 byte数组 信息如下:

97,49,233,131,173,231,186,162,228,191,138,98,50

接受时,接受到的 byte 数组信息就变成了

97,49,239,191,189,239,191,189,98,50

 

原先的 BinaryReader dis 其实是个这个开源组件自己写的派生自BinaryReader 的  OpenWireBinaryReader 类。这个类有很多不完善的地方。

这部分的逻辑可以在 TcpTransport 类的下面调用中看到

private readonly Socket socket;
private BinaryReader socketReader;

socketReader = new OpenWireBinaryReader(new NetworkStream(socket));

原先的 OpenWireBinaryReader  不完善的地方:

1、传送中文时,会丢数据;ms.WriteByte((byte)nextChar); 会让本来nextChar对应的 byte 数组,只取了数组的第一项,数组的其他项则丢失了;

2、编码混乱,unicode 和 utf-8 转换有问题。

 

参考资料:

Apache ActiveMQ
http://activemq.apache.org/

ActiveMQ .NET
http://activemq.apache.org/nms/


推荐阅读
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
  • 1jdk去网站下载,然后拷贝到linux上;或直接wgethttp:download.oracle.comotn-pubjavajdk8u181-b1 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
  • python3 nmap函数简介及使用方法
    本文介绍了python3 nmap函数的简介及使用方法,python-nmap是一个使用nmap进行端口扫描的python库,它可以生成nmap扫描报告,并帮助系统管理员进行自动化扫描任务和生成报告。同时,它也支持nmap脚本输出。文章详细介绍了python-nmap的几个py文件的功能和用途,包括__init__.py、nmap.py和test.py。__init__.py主要导入基本信息,nmap.py用于调用nmap的功能进行扫描,test.py用于测试是否可以利用nmap的扫描功能。 ... [详细]
  • 本文介绍了使用readlink命令获取文件的完整路径的简单方法,并提供了一个示例命令来打印文件的完整路径。共有28种解决方案可供选择。 ... [详细]
  • 本文介绍了在RHEL 7中的系统日志管理和网络管理。系统日志管理包括rsyslog和systemd-journal两种日志服务,分别介绍了它们的特点、配置文件和日志查询方式。网络管理主要介绍了使用nmcli命令查看和配置网络接口的方法,包括查看网卡信息、添加、修改和删除配置文件等操作。 ... [详细]
  • 本文介绍了Java调用Windows下某些程序的方法,包括调用可执行程序和批处理命令。针对Java不支持直接调用批处理文件的问题,提供了一种将批处理文件转换为可执行文件的解决方案。介绍了使用Quick Batch File Compiler将批处理脚本编译为EXE文件,并通过Java调用可执行文件的方法。详细介绍了编译和反编译的步骤,以及调用方法的示例代码。 ... [详细]
  • SQL Server中TempDB管理(version store的逻辑 ... [详细]
author-avatar
逝去成回忆2502920253
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有