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
UserInfos.cs
namespace WcfModel
{
[DataContract]
public class UserInfo
{
[DataMember]
public int Id { get; set; }
public string Name { get; set; }
}
}
MessageInfo.cs
public class MessageInfo
public UserInfo FromUser { get; set; }
public UserInfo ToUser { get; set; }
public string Content { get; set; }
public DateTime SendTime { get; set; }
}
右键此项目,生成。
IMessageCallBack.cs
namespace WcfContract
public interface IMessageCallBack
[OperationContract(IsOneWay = true)]
void GetMessage(MessageInfo message);
IMessageManage.cs
[ServiceContract(CallbackContract = typeof(IMessageCallBack))]
public interface IMessageManage
[OperationContract]
bool SendMessage(MessageInfo msg);
bool RequestMessage(UserInfo user);
右键此项目生成。
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);
<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>
右键生成些项目
右击应用程序池,添加应用程序池,命名为WcfNetTcp,版本选择.net framework v4.0.30319
点击网站的高级设置在“已启用的协议”中添加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根目录是此网站的根目录,地方要找正确
点击引用,添加服务器引用,输入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" Click="btncreateuser1_Click" />
<Button x:Name="btncreateuser2" Content="生成用户2" Width="100" Margin="0,0" Click="btncreateuser2_Click"/>
<TextBox x:Name="tbContent" Width="200" Height="150" Margin="0,0"/>
<Button x:Name="btnSend" Content="发送" Width="100" Margin="0,0" Click="btnSend_Click"/>
<TextBox x:Name="tbContentRecord" Width="200" Height="150" Margin="0,245)"> </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,245)"> UserInfo formUser = new UserInfo()
Id = 123,
Name = "张三"
UserInfo toUser = new UserInfo()
Id = 234,245)"> Name = "李四",245)"> message.FromUser = formUser;
message.ToUser = toUser;
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,245)"> Name = "李四"
Name = "张三",245)"> MessageBox.Show("用户" + formUser.Id + "创建成功!");
client.GetMessageReceived += (gs,245)"> }
成功后,就可相互发送信息了
后记。对于net.tcp双工有时候真心让人不知道问题在那儿,什么跨域XML。配置文件这些都没问题,有时候就是还是要报什么跨域错误,有时候又不报跨域错误,真让人摸不着头脑,如果有对此了解深刻的,请大神指点。
源码地址:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。