• silverlight+WCF的net.tcp双工通信实例过程


    silverlight+WCF的net.tcp双工通信实例过程

    注:本人只是一个菜鸟,有什么不对的,请各位大侠指正,成分感谢!!!

    本实例实现一个简单的单用户对单用户的消息发送实例。实例开始:

    1. 进行net.tcp双工通信必须安装Windows功能下的Microsoft.NET.Framework3.5.1下面两项
    2. 项目结构如下:

             

    说明:SilverlightApp silverlight项目,其网页承载与WCF服务是一个WEB项目,即WcfService

          WcfContract 一个类库项目,用于定义契约,需引用System.ServiceModel

          WcfModel一个类库项目,用于定义数据实体类,需要引用System.Runtime.Serialization

    WcfService 一个web项目,用于IIS寄存WCF

    1. 新建一个解决方案命名为nettcpTest
    2. 在解决方案上添加一个类库项目:WcfModel,在此类库项目中添加两个类UserInfo、MessageInfo 。

    UserInfos.cs

    namespace WcfModel

    {

        [DataContract]

        public class UserInfo

        {

            [DataMember]

            public int Id { get; set; }

            [DataMember]

            public string Name { get; set; }

        }

    }

    MessageInfo.cs

    namespace WcfModel

    {

        [DataContract]

        public class MessageInfo

        {

            [DataMember]

            public UserInfo FromUser { get; set; }

            [DataMember]

            public UserInfo ToUser { get; set; }

            [DataMember]

            public string Content { get; set; }

            [DataMember]

            public DateTime SendTime { get; set; }

        }

    }

    右键此项目,生成。

    1. 右键解决方案添加一个名为WcfContract的类库项目,引用WcfModel,在项目中添加两个接口:IMessageCallBack、IMessageManage

    IMessageCallBack.cs

    namespace WcfContract

    {

        public interface IMessageCallBack

        {

            [OperationContract(IsOneWay = true)]

            void GetMessage(MessageInfo message);

        }

    }

    IMessageManage.cs

    namespace WcfContract

    {

        [ServiceContract(CallbackContract = typeof(IMessageCallBack))]

        public interface IMessageManage

        {

            [OperationContract]

            bool SendMessage(MessageInfo msg);

            [OperationContract]

            bool RequestMessage(UserInfo user);

        }

    }

    右键此项目生成。

    1. 在解决方案上添加一个空的web项目,名称为WcfService,并引用前两个类库。并且添加一个WCF服务命名为MessageService.svc,删除原有的接口,后台代码如下:

    MessageService.cs

    namespace WcfService

    {

        // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“MessageService”。

        // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 MessageService.svc 或 MessageService.svc.cs,然后开始调试。

        public class MessageService :IMessageManage

        {

            //用于记录用户与对应的通道

            private static Dictionary<int, IMessageCallBack> DicCallChannel = new Dictionary<int, IMessageCallBack>();

            //记录间用户的ID

            private int UserId = 0;

     

            public bool SendMessage(WcfModel.MessageInfo msg)

            {

                //获取对应要发送的通道,回调

                if (DicCallChannel.Keys.Contains(msg.ToUser.Id))

                {

                    DicCallChannel[msg.ToUser.Id].GetMessage(msg);

                    return true;

                }

                return false;

            }

     

            public bool RequestMessage(WcfModel.UserInfo user)

            {

                //获取用户请求建立的通道

                IMessageCallBack channel = OperationContext.Current.GetCallbackChannel<IMessageCallBack>();

                if (!DicCallChannel.Keys.Contains(user.Id))

                {

                    DicCallChannel.Add(user.Id, channel);

                    UserId = user.Id;                

                    OperationContext.Current.Channel.Closing += Channel_Closing;

                }

                return true;

            }

            //当用户通道关闭时,把用户的通道记录删除,即不记录已经断开的通道

            void Channel_Closing(object sender, EventArgs e)

            {

                if (DicCallChannel.Keys.Contains(UserId))

                {

                    DicCallChannel.Remove(UserId);

                }

            }

        }

    }

    1. 打开web.config,添加如下节点

     <system.serviceModel>

        <behaviors>

          <serviceBehaviors>

            <behavior name="mBehavior">

              <serviceMetadata httpGetEnabled="false" />

              <serviceDebug includeExceptionDetailInFaults="true" />

            </behavior>

          </serviceBehaviors>

        </behaviors>

        <bindings>

          <netTcpBinding>

            <binding name="mBinding">

              <security mode="None" />

            </binding>

          </netTcpBinding>

        </bindings>

        <services>

          <service name="WcfService.MessageService" behaviorConfiguration="mBehavior">

            <endpoint address="" binding="netTcpBinding" bindingConfiguration="mBinding" contract="WcfContract.IMessageManage" />

            <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />

          </service>

        </services>

        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

      </system.serviceModel>

        <system.webServer>

            <directoryBrowse enabled="true" />

    </system.webServer>

    右键生成些项目

    1. 打开IIS管理器,如果IIS没有安装.net4.0,则IIS需要注册net4.0,怎么注册,大家问度娘吧

     

    右击应用程序池,添加应用程序池,命名为WcfNetTcp,版本选择.net framework v4.0.30319

     

    1. 右击网站 ,添加网站,网站名为WcfNetTcp,程序池选择WcfNetTcp,物理路径选择刚刚解决方案中WEB项目WcfService的物理路径,端口我这里设置的是8081

    点击网站的高级设置在“已启用的协议”中添加net.tcp

     

    右击网站,编辑协议-添加,选择net.tcp,绑定信息输入4507:*,确定

    点击浏览网站,会列出如下信息

    选择MessageService.svc链接,也可直接在浏览器上输入http://localhost:8081/MessageService.svc

    浏览器会显示如下:

    已创建服务。

    若要测试此服务,需要创建一个客户端,并将其用于调用该服务。可以使用下列语法,从命令行中使用 svcutil.exe 工具来进行此操作:



    svcutil.exe net.tcp://barry:4507/MessageService.svc/mex

    为了让WCF能够跨域,需要在IIS的默认网站根目录下添加clientaccesspolicy.xml,有必要时还添加crossdomain.xml

    clientaccesspolicy.xml

    <?xml version="1.0" encoding="utf-8" ?>

    <access-policy>

       <cross-domain-access>

          <policy>

             <allow-from http-request-headers="*">

                <domain uri="*" />

             </allow-from>

             <grant-to>

                <socket-resource port="4502-4534" protocol="tcp" />

                <resource path="/" include-subpaths="true"/>

             </grant-to>

          </policy>

       </cross-domain-access>

    </access-policy>

    crossdomain.xml

    <?xml version="1.0" ?>

    <cross-domain-policy>

      <allow-access-from domain="*" />

    </cross-domain-policy>

    IIS默认网站是Default Web Site根目录是此网站的根目录,地方要找正确

     

    1. 回到项目中,在解决方案中,添加一个名为SilverlightApp的silverlight程序,

    点击引用,添加服务器引用,输入net.tcp://localhost:4507/MessageService.svc/mex

    在高级中,在字典信息类型中取消 重新使用引用的程序集中的类型

     

    确定添加

    MainPage界面设计:

    <UserControl x:Class="SilverlightApp.MainPage"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        d:DesignHeight="300" d:DesignWidth="400">

     

        <Grid x:Name="LayoutRoot" Background="White">

            <StackPanel Orientation="Vertical">

                <Button x:Name="btnCreateUser1" Content="生成用户1" Width="100" Margin="0,10,0,0" Click="btnCreateUser1_Click" />

                <Button x:Name="btnCreateUser2" Content="生成用户2" Width="100" Margin="0,10,0,0" Click="btnCreateUser2_Click"/>

                <TextBox x:Name="tbContent" Width="200" Height="150" Margin="0,10,0,0"/>

                <Button x:Name="btnSend" Content="发送" Width="100" Margin="0,10,0,0" Click="btnSend_Click"/>

                <TextBox x:Name="tbContentRecord" Width="200" Height="150" Margin="0,10,0,0"/>

            </StackPanel>

        </Grid>

    </UserControl>

    后台代码:

    public partial class MainPage : UserControl

        {

          

            MessageInfo message = new MessageInfo();

            public MainPage()

            {

                InitializeComponent();

              

            }

     

            private void btnSend_Click(object sender, RoutedEventArgs e)

            {

                MessageManageClient client = new MessageManageClient();

                message.Content = tbContent.Text;

                message.SendTime = DateTime.Now;

                client.SendMessageAsync(message);

                client.SendMessageCompleted += (ds, de) =>

                {

                    if (de.Result)

                    {

                        MessageBox.Show("发送成功!");

                    }

                    else

                    {

                        MessageBox.Show("发送失败!");

                    }

                };

            }

     

            private void btnCreateUser1_Click(object sender, RoutedEventArgs e)

            {

                MessageManageClient client = new MessageManageClient();

                UserInfo formUser = new UserInfo()

                {

                    Id = 123,

                    Name = "张三"

                };

                UserInfo toUser = new UserInfo()

                {

                    Id = 234,

                    Name = "李四",

                };

     

                message.FromUser = formUser;

                message.ToUser = toUser;

                message.Content = tbContent.Text;

                message.SendTime = DateTime.Now;

                client.RequestMessageAsync(formUser);

                client.RequestMessageCompleted += (rs, re) =>

                {

                    if (re.Result)

                    {

                        MessageBox.Show("用户"+formUser.Id+"创建成功!");

                    }

                };

                client.GetMessageReceived += (gs, ge) =>

                {

                    if (ge.Error == null)

                    {

                        tbContentRecord.Text += " " + "来自:" + ge.message.FromUser.Name + ",内容:" + ge.message.Content + ",时间:" + ge.message.SendTime.ToShortTimeString();

                    }

                };

            }

     

            private void btnCreateUser2_Click(object sender, RoutedEventArgs e)

            {

                MessageManageClient client = new MessageManageClient();

                UserInfo formUser = new UserInfo()

                {

                    Id = 234,

                    Name = "李四"

                };

                UserInfo toUser = new UserInfo()

                {

                    Id = 123,

                    Name = "张三",

                };

     

                message.FromUser = formUser;

                message.ToUser = toUser;

                message.Content = tbContent.Text;

                message.SendTime = DateTime.Now;

                client.RequestMessageAsync(formUser);

                client.RequestMessageCompleted += (rs, re) =>

                {

                    if (re.Result)

                    {

                        MessageBox.Show("用户" + formUser.Id + "创建成功!");

                    }

                };

                client.GetMessageReceived += (gs, ge) =>

                {

                    if (ge.Error == null)

                    {

                        tbContentRecord.Text += " " + "来自:" + ge.message.FromUser.Name + ",内容:" + ge.message.Content + ",时间:" + ge.message.SendTime.ToShortTimeString();

                    }

                };

            }

    }

    1. 将WcfService项目设为启动项目,将SilverlightAppTestPage.html设为启动页面,

     

    F5运行程序,复制页面路径,同时打开两个相同的页面

    两个页面分别点生成用户1、生成用户2,

     

    成功后,就可相互发送信息了

     

    后记。对于net.tcp双工有时候真心让人不知道问题在那儿,什么跨域XML。配置文件这些都没问题,有时候就是还是要报什么跨域错误,有时候又不报跨域错误,真让人摸不着头脑,如果有对此了解深刻的,请大神指点。

    源码地址:

    http://download.csdn.net/detail/cyb331/5657061
    源码
    不小心加上分了,需要的留下邮箱

  • 相关阅读:
    memcached的PHP扩展之PECL/memcache与PECL/memcached区别
    SQL*PLUS SET变量
    Centos中安装memcached
    HP Unix常用命令
    phpmbstring
    安装memcache到CentOS(另附yum法)
    CF Educational Codeforces Round 57划水记
    [NOIP2018]旅行(数据加强版)(图论+基环树)
    JavaScript DOM高级程序设计
    应用程序权限设计
  • 原文地址:https://www.cnblogs.com/cyb331/p/3158285.html
Copyright © 2020-2023  润新知