2012-07-18 40 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