对 ActiveMQ .NET 1.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: " + 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("<<<< header: " + 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("<<<< error reading frame null byte.");
		}
	}
	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("<<<< received: " + 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: " + 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("<<<< header: " + 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("<<<< received: " + 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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值