输入流不是有效格式

输入流不是有效格式

本文介绍了.NET智能卡 - 序列化/反序列化远程对象。输入流不是有效格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用.NET智能卡,它具有.NET远程相同的概念。

所以我的智能卡(如服务器)有这样的服务:

 公共类的MyService:MarshalByRefObject的
{
     字符串=ABC;

    公共字节[] MySampleMethod()
    {
        为MyService的obj =新的MyService();
        返回help.ObjectToByteArray(OBJ);
    }}}
 

这是ObjectToByteArray(OBJ)

 公共静态的byte [] ObjectToByteArray(为MyService OBJ)
    {
        如果(OBJ == NULL)
            返回null;
        BinaryFormatter的BF =新的BinaryFormatter();
        MemoryStream的毫秒=新的MemoryStream(0);
        bf.Serialize(MS,OBJ);
        返回ms.ToArray();
    }
 

至于客户端:

 公共静态无效的主要()
    {
        //创建和注册通信通道
        APDUClientChannel通道=新APDUClientChannel();
        ChannelServices.RegisterChannel(信道);

        //获取和借鉴远程对象
        为MyService服务=(则将MyService)Activator.GetObject(typeof运算(为MyService),URL);

        //调用远程方法
        byte []的结果= service.MySampleMethod();

        为MyService OBJ = ByteArrayToObject(结果);

        Console.WriteLine(结果[0]);
        到Console.ReadLine();
        //注销的通信信道
        ChannelServices.UnregisterChannel(信道);
    }
 

ByteArrayToObject

 公共静态为MyService ByteArrayToObject(byte []的arrBytes)
    {
        MemoryStream的memStream =新的MemoryStream(0);
        BinaryFormatter的binForm =新的BinaryFormatter();
        memStream.Write(arrBytes,0,arrBytes.Length);

        memStream.Seek(0,SeekOrigin.Begin);
        //memStream.Position = 0;
        为MyService OBJ =(则将MyService)binForm.Deserialize(memStream);
        返回OBJ;
    }
 

现在的问题是,当我想反序列化对象。

我测试这个字符串ABCDE,它在卡序列化,其结果是十六进制:

而当我在我的电脑序列化的结果是:

所以,在我的PC应用程序,反序列化的第二个效果很好,但是当我反序列化的第一个字符串(从智能卡),我得到了:

解决方案

Gemalto.NET智能卡只支持通过引用编组,因此任何原始的结构类型,你有可能在客户端,而序列化的需求,因为可以访问的服务器你已经通过远程调用该对象的引用:

所以先登记您的服务:

 公共类要播
    {
        ///<总结>
        ///指定暴露远程对象的URI。
        ///< /总结>
        私人常量字符串REMOTE_OBJECT_URI =MyService.uri;

        ///<总结>
        ///注册服务器到存储卡。
        ///< /总结>
        ///<返回>< /回报>
        公共静态INT主要()
        {
            //注册服务器将侦听到信道。
            ChannelServices.RegisterChannel(新APDUServerChannel());

            //注册本申请作为服务器
            RemotingConfiguration.RegisterWellKnownServiceType(typeof运算(为MyService),REMOTE_OBJECT_URI,WellKnownObjectMode.Singleton);

            返回0;
        }
    }
 

和再定义的服务类,您可以返回原始类型和结构,对金雅拓文档:

 公共类的MyService:MarshalByRefObject的
    {
        公共结构的人
        {
            公共字符串名称;
            公众诠释ID;

            公众人物(INT ID,字符串名称)
            {
                this.name =名称;
                this.id = ID;
            }

            公共字符串的getName()
            {
                返回this.name;
            }

            公众诠释的getId()
            {
                返回this.id;
            }
        }

        公共字符串MySampleMethod()
        {
            返回这是返回字符串;
        }

        公众人物getPerson()
        {
            人人=新的Person(15,Wajdy);
            返回的人;
        }
    }
 

现在的客户端应用程序,您将有引用服务对象并且可以正常调用的方法:

 公共类MyClient
    {
        私人常量字符串URL =APDU://selfdiscover/MyService.uri;

        公共静态无效的主要()
        {
            //创建和注册通信通道
            APDUClientChannel通道=新APDUClientChannel();
            ChannelServices.RegisterChannel(信道);

            //获取和借鉴远程对象
            为MyService服务=(则将MyService)Activator.GetObject(typeof运算(为MyService),URL);
            Console.WriteLine(service.MySampleMethod());

            MyService.Person人= service.getPerson();
            Console.WriteLine(person.getName());
            Console.WriteLine(person.getId());

            到Console.ReadLine();

            //注销的通信信道
            ChannelServices.UnregisterChannel(信道);
        }
    }
 

I am using .NET smart card, it has the same concepts of .NET remoting.

So my smartcard (as a server) has this service:

public class MyService : MarshalByRefObject
{
     string a = "abC";

    public byte[] MySampleMethod()
    {
        MyService obj = new MyService();
        return help.ObjectToByteArray( obj);
    }}}

and this is ObjectToByteArray(obj)

public static byte[] ObjectToByteArray(MyService obj)
    {
        if (obj == null)
            return null;
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream(0);
        bf.Serialize(ms, obj);
        return ms.ToArray();
    }

As for client :

    public static void Main()
    {
        // create and register communication channel
        APDUClientChannel channel = new APDUClientChannel();
        ChannelServices.RegisterChannel(channel);

        // get the referenc to remote object
        MyService service = (MyService)Activator.GetObject(typeof(MyService), URL);

        // invoke the remote method
        byte[] result = service.MySampleMethod();

        MyService obj = ByteArrayToObject(result);

        Console.WriteLine(result[0]);
        Console.ReadLine();
        // unregister the communication channel
        ChannelServices.UnregisterChannel(channel);
    }

ByteArrayToObject

    public static MyService ByteArrayToObject(byte[] arrBytes)
    {
        MemoryStream memStream = new MemoryStream(0);
        BinaryFormatter binForm = new BinaryFormatter();
        memStream.Write(arrBytes, 0, arrBytes.Length);

        memStream.Seek(0, SeekOrigin.Begin);
        //memStream.Position = 0;
        MyService obj = (MyService)binForm.Deserialize(memStream);
        return obj;
    }

The problem is when I want to Deserialize the object.

I test this string "ABCDE" , serialize it in the card and the result hex is :

WHILE the result when i serialize it on my pc is :

So on my PC application, deserializing the second one works well, but when i deserialize the first string (from smart card) I got :

解决方案

Gemalto.NET Smart Card supports only marshalling by reference, so any primitive and struct types you have in the server can be accessed in client without the need of serialization because you already have the reference to the object through remote invocation:

so first register your service:

public class MyServer
    {
        /// <summary>
        /// specify the exposed remote object URI.
        /// </summary>
        private const string REMOTE_OBJECT_URI = "MyService.uri";

        /// <summary>
        /// Register the server onto the card.
        /// </summary>
        /// <returns></returns>
        public static int Main()
        {
            // Register the channel the server will be listening to.
            ChannelServices.RegisterChannel(new APDUServerChannel());

            // Register this application as a server
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyService), REMOTE_OBJECT_URI, WellKnownObjectMode.Singleton);

            return 0;
        }
    }

and then define the service class, and you can return primitive types and struct, for gemalto docs:

public class MyService : MarshalByRefObject
    {
        public struct Person
        {
            public string name;
            public int id;

            public Person(int id, string name)
            {
                this.name = name;
                this.id = id;
            }

            public string getName()
            {
                return this.name;
            }

            public int getId()
            {
                return this.id;
            }
        }

        public string MySampleMethod()
        {
            return "This is return String";
        }

        public Person getPerson()
        {
            Person person = new Person(15, "Wajdy");
            return person;
        }
    }

Now in the client application, you will have the reference to service object and you can call the methods normally:

public class MyClient
    {
        private const string URL = "apdu://selfdiscover/MyService.uri";

        public static void Main()
        {
            // create and register communication channel
            APDUClientChannel channel = new APDUClientChannel();
            ChannelServices.RegisterChannel(channel);

            // get the referenc to remote object
            MyService service = (MyService)Activator.GetObject(typeof(MyService), URL);
            Console.WriteLine(service.MySampleMethod());

            MyService.Person person = service.getPerson();
            Console.WriteLine(person.getName());
            Console.WriteLine(person.getId());

            Console.ReadLine();

            // unregister the communication channel
            ChannelServices.UnregisterChannel(channel);
        }
    }

这篇关于.NET智能卡 - 序列化/反序列化远程对象。输入流不是有效格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 01:44