2012-07-18 39 views
0

我有一個系統,我可以在Windows和嵌入式系統之間通過不同的點到點通信通道交換消息,而且完全可以作爲非常標準的自定義序列化/反序列化函數完成,幾乎完全由手工完成,因爲這使得它很容易在Windows端的C#和嵌入的C端口之間移植。爲什麼我得到wcf反序列化的空數據?

現在我想添加一個大型網絡上的PC之間進行通信的塊。而不是做另一批相同的東西,使用TcpClient/TcpListener並跟蹤重疊的消息和響應,我決定看看WCF。

在看過很多關於這裏的信息以及其他文檔等信息之後,我想出了一個非常簡單的應用程序來交換消息,服務器包含一個接收和返回接口實例的函數,而不是一個固定的類。即使這個例子只有一種消息,因此只有一種類型是使用KnownType和ServiceKnownType屬性設置的,但我想知道可以發送幾十種不同類型的消息,並且我希望能夠添加它們隨着事物的發展相當容易。

雖然代碼不會生成錯誤,但在遠端實例化的對象沒有任何已發送的數據。我嘗試過數據包嗅探,看看我是否可以確認數據實際上在線路上,但我無法理解線路協議。所以我不知道數據在傳輸中還是在服務器中消失。如果我將代碼更改爲直接使用TestMessageType實例而不是使用接口,則它可以正常工作。

該解決方案由三個項目組成;一個「類型」程序集,然後引用該程序集的客戶端和服務器控制檯應用程序。類型程序集包含此代碼;

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ServiceModel; 
using System.Runtime.Serialization; 

namespace WCF_TCP_Sandpit 
{ 

    public interface ITestInterface 
    { 
     Int64 I64Value {get; set;} 
    } 

    [ServiceContract] 
    public interface IServer 
    { 
     [OperationContract] 
     [ServiceKnownType(typeof(TestMessageType))] 
     ITestInterface Test(ITestInterface msg); 
    } 

    [DataContract] 
    [KnownType(typeof(TestMessageType))] 
    public class TestMessageType : ITestInterface 
    { 
     Int64 _v1; 

     public long I64Value 
     { 
      get { return _v1; } 
      set { _v1 = value; } 
     } 

     public static Type[] KnownTypes() 
     { 
      return new Type[] { typeof(TestMessageType) }; 
     } 
    } 
} 

服務器代碼

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ServiceModel; 
using WCF_TCP_Sandpit; 
using System.Runtime.Serialization; 

namespace Server 
{ 
    class Program : IServer 
    { 
     static void Main(string[] args) 
     { 
      using (ServiceHost serviceHost = new ServiceHost(typeof(Program), new Uri("net.tcp://127.0.0.1:9000"))) 
      { 
       serviceHost.Open(); 

       // The service can now be accessed. 
       Console.WriteLine("The service is ready."); 
       Console.WriteLine("Press <ENTER> to terminate service."); 
       Console.WriteLine(); 
       Console.ReadLine(); 
      } 

     } 

     #region IServer Members 

     public ITestInterface Test(ITestInterface msg) 
     { 
      ITestInterface reply = new TestMessageType(); 

      reply.I64Value = msg.I64Value * 2; 
      return reply; 
     } 

     #endregion 
    } 
} 

和客戶端的代碼是

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using WCF_TCP_Sandpit; 

using System.ServiceModel; 

namespace Client 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      ITestInterface m,r; 
      int i = 0; 
      ChannelFactory<WCF_TCP_Sandpit.IServer> srv 
       = new ChannelFactory<WCF_TCP_Sandpit.IServer> 
       (new NetTcpBinding(), "net.tcp://127.0.0.1:9000"); 

      WCF_TCP_Sandpit.IServer s; 
      s = srv.CreateChannel(); 

      while (true) 
      { 
       m = new WCF_TCP_Sandpit.TestMessageType(); 
       m.I64Value = i++; 

       r = s.Test(m); 

       Console.WriteLine("Sent " + m.I64Value + "; received " + r.I64Value); 
       System.Threading.Thread.Sleep(1000); 
      } 
     } 
    } 
} 

任何人都可以投在什麼地方出了錯一些輕?

+0

當你檢查數據包(當它工作)它使用XML?我不記得wcf是否會使用xml序列化程序,但它可能會。 (從進一步閱讀看來,二進制序列化器使用ootb)。你有沒有試過把你的ITestMessage包裝成一個'Message'類(即讓ITestMessage成爲這個Message類的屬性) – wal 2012-07-18 15:10:05

回答

0

您是否需要I64Value屬性上的DataMember屬性?

+0

很明顯:)在轉換到界面時可能會丟失它而沒有被分割。 Wal-it純粹的二進制。我什至不能看到任何特定的值遞增。但是,因爲它不是首先序列化的,所以我不會有。 感謝您的幫助。 – 2012-07-19 08:00:58