0

私は、Windowsと組み込みシステムの間の異なるポイントツーポイント通信チャネルでメッセージを交換しているシステムを持っており、非常に標準的なカスタムのシリアライズ/デシリアライズ機能としてすべてを手作業で行っています。 Windows 側の C# と組み込み側の C の間を移植します。

ここで、ネット全体の PC 間で通信するチャンクを追加したいと考えています。同じことを別のバッチで行うのではなく、TcpClient/TcpListener を使用して重複するメッセージと応答を追跡するのではなく、WCF を調べることにしました。

ここで多くのメッセージや他の場所のドキュメントなどを見た後、メッセージを交換する非常に単純なアプリを思いつきました。サーバーには、固定クラスではなく、インターフェイス インスタンスを受け取って返す関数が 1 つ含まれています。この例には 1 種類のメッセージしかありませんが、KnownType 属性と ServiceKnownType 属性を使用して設定されるタイプは 1 つだけですが、送信できるメッセージの種類が数十種類あることを想像して、それらを追加できるようにしたいと考えています。物事が進化するにつれて、かなり簡単に。

コードによってエラーは生成されませんが、遠端でインスタンス化されたオブジェクトには、送信されたデータがまったく含まれていません。データが実際にネットワーク上を移動していることを確認できるかどうかを確認するためにパケット スニッフィングを試みましたが、ワイヤ プロトコルを理解できません。そのため、送信時にクライアントでデータが消えているのか、サーバーでデータが消えているのかわかりません。インターフェイスを使用するのではなく、TestMessageType のインスタンスを直接使用するようにコードを変更すると、問題なく動作します。

このソリューションは 3 つのプロジェクトで構成されています。「型」アセンブリ、およびそのアセンブリを参照するクライアントおよびサーバー コンソール アプリ。型アセンブリにはこのコードが含まれています。

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

何がうまくいかないのか、誰かが光を当てることができますか?

4

1 に答える 1

0

DataMemberプロパティに属性は必要ありませんI64Valueか?

于 2012-07-18T15:18:50.073 に答える