2013-03-05 35 views
1

我使用.NET智能卡,它具有與.NET遠程處理相同的概念。.NET smartcard - 序列化/反序列化遠程對象。輸入流不是有效格式

所以我的智能卡(服務器)有這樣的服務:

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

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

,這是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(); 
    } 

至於客戶端:

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; 
    } 

問題是當我想反序列化對象。

我測試這個字符串 「ABCDE」,在卡和結果的十六進制序列是:

1C-5D-D2-00-27-11-02-00-00-00-05 -00-00-00-05-00-00-00-01-41-00-42-00-43-00-44-00 -45-00

WHILE當我序列化它的結果在我的電腦上是:

00-01-00-00-00-FF-FF-FF-FF-01-00-00-00-00-00-00-00-06-01-00 -00-00-05-41-42-43-44 -45-0B。

所以在我的PC應用程序,反序列化的第二個效果很好,但是當我反序列化的第一個字符串(從智能卡)我:

「的輸入流不是有效的二進制格式。起始內容(以字節爲單位)爲:1C-5D-D2-00-27-11-02-00-00-00-05-00-00-00-05-00-00 ...「

+0

你缺少的「T」在上面的十六進制字符串:P ,嚴重的是,我不是。NET卡專家,但客戶如何知道哪種對象被序列化?如果可能,請顯示完整的二進制格式。 – 2013-03-05 23:13:26

+0

你是什麼意思「客戶端如何知道」,實際上我在客戶端添加服務器.exe的引用,如果這是你要求的 – 2013-03-07 10:22:37

+0

你有更多的數據嗎?第一個字節從上面的「起始內容」中丟失,它似乎是某種類型的指示符,它以「(T)ypeLoadSTEx」的ASCII編碼開始......嗯,可能是某種異常而不是對象? – 2013-03-07 23:16:32

回答

2

Gemalto.NET智能卡僅支持引用編組,因此您可以在客戶端訪問服務器中的任何基元和結構類型而無需序列化因爲使用您已經有通過遠程調用該對象的引用:

所以先註冊服務:

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; 
     } 
    } 

,然後定義服務類,你可以返回原始類型和結構,對金雅拓文檔:可編組

類型包括基本值類型(字節, 短,字符型,整型,長整型,字符串等),結構,基本類型的數組, 和MemoryStreams

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; 
     } 
    } 

現在在客戶端應用程序,你將有參考服務對象,並可以正常調用的方法:

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); 
     } 
    }