您的位置:首页 > 理论基础 > 计算机网络

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

2013-06-27 10:55 183 查看
silverlight+WCF的net.tcp双工通信实例过程

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

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

进行net.tcp双工通信必须安装Windows功能下的Microsoft.NET.Framework3.5.1下面两项



项目结构如下:



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

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

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

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

新建一个解决方案命名为nettcpTest

在解决方案上添加一个类库项目: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; }

}

}

右键此项目,生成。

右键解决方案添加一个名为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);

}

}

右键此项目生成。

在解决方案上添加一个空的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);

}

}

}

}

打开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>

右键生成些项目

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



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



右击网站 ,添加网站,网站名为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根目录是此网站的根目录,地方要找正确



回到项目中,在解决方案中,添加一个名为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 += "\r"
+ "来自:" + 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 += "\r"
+ "来自:" + ge.message.FromUser.Name + ",内容:" +
ge.message.Content + ",时间:" +
ge.message.SendTime.ToShortTimeString();

}

};

}

}

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



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



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



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



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

源码地址:

http://download.csdn.net/detail/cyb331/5657061
源码
不小心加上分了,需要的留下邮箱
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐