Artech

Develop every application as an art using the most suitable technologies!

常用链接

统计

积分与排名

网上邻居

我的博文系列

最新评论

[原创]我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯

在一个基于面向服务的分布式环境中,借助一个标准的、平台无关的Communication Infrastructure,各个Service通过SOAP Message实现相互之间的交互。这个交互的过程实际上就是Message Exchange的过程。WCF支持不同形式的Message Exchange,我们把这称之为Message Exchange Pattern(MEP), 常见的MEP包括: Request/Reply,Request/Forget(One-way)和Duplex。通过采用Duplex MEP,我们可以实现在Service端Callback Client的操作。虽然WCF为我们实现底层的通信细节,使得我们把精力转移到业务逻辑的实现,进行Transport无关的编程,但是对底层Transport的理解有利于我们根据所处的具体环境选择一个合适的Transport。说到Transport, WCF 经常使用的是以下4个:Http,TCP,Named Pipe,MSMQ。由于不同协议自身的差异,他们对具体MEP的支持方式也会不同,我们今天就来谈谈Http和TCP对Duplex的支持。

一、Sample

为了使大家对在WCF如何实现双向通信(Bidirectional Communication)有一个直观的理解,我们先来看一个简单的Sample。我们照例采用下面的4层结构和Calculator的例子:


1.Contract:Artech.DuplexWCF.Contract. ICalculator

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;

namespace Artech.DuplexWCF.Contract
{
    [ServiceContract(CallbackContract 
= typeof(ICallback))]
    
public interface ICalculator
    
{
        [OperationContract(IsOneWay 
= true)]
        
void Add(double x, double y);
    }

}

由于模拟的是通过Callback来显示Add方法计算的结果,我把Add Operation设置成One-way。在Service Contract中设置了Callback Contract,Callback Contract定义在Interface Artech.DuplexWCF.Contract. ICallback中:

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;

namespace Artech.DuplexWCF.Contract
{
    [ServiceContract]
    
public interface ICallback
    
{
        [OperationContract(IsOneWay 
= true)]
        
void DisplayResult(double result);
    }

}

2.Service: Artech.DuplexWCF.Service. CalculatorService

using System;
using System.Collections.Generic;
using System.Text;
using Artech.DuplexWCF.Contract;
using System.ServiceModel;

namespace Artech.DuplexWCF.Service
{
    
public class CalculatorService:ICalculator
    
{
        
ICalculator Members
    }

}

在Service端,通过OperationContext.Current.GetCallbackChannel来获得Ciient指定的CallbackContext instance,进而调用Client的Operation。

3.Hosting:

Configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<system.serviceModel>        
        
<services>
            
<service name="Artech.DuplexWCF.Service.CalculatorService">
                
<endpoint address="net.tcp://localhost:9999/calculator"  binding="netTcpBinding" contract="Artech.DuplexWCF.Contract.ICalculator" />                
            
</service>
        
</services>
    
</system.serviceModel>
</configuration>

我们通过netTcpBinding来模拟基于TCP的双向通信。

Program:

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using Artech.DuplexWCF.Service;

namespace Artech.DuplexWCF.Hosting
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            
using (ServiceHost calculatorHost = new ServiceHost(typeof(CalculatorService)))
            
{
                calculatorHost.Opened 
+= delegate
                
{
                    Console.WriteLine(
"The calculator service has begun to listen");
                }
;
                calculatorHost.Open();
                Console.Read();
            }

        }

    }

}

4.Client:

Configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
<system.serviceModel>
        
<client>
            
<endpoint address="net.tcp://localhost:9999/calculator" binding="netTcpBinding"
                bindingConfiguration
="" contract="Artech.DuplexWCF.Contract.ICalculator"
                name
="defaultEndpoint" />
        
</client>
    
</system.serviceModel>
</configuration>

Callback:Artech.DuplexWCF.Client. CalculatorCallback

using System;
using System.Collections.Generic;
using System.Text;
using Artech.DuplexWCF.Contract;

namespace Artech.DuplexWCF.Client
{
    
public class CalculatorCallback:ICallback
    
{
        
ICallback Members
    }

}

Callback的操作-显示计算结果,实现在Artech.DuplexWCF.Client. CalculatorCallback中,他实现了在Contract中定义的Callback Contract:Artech.DuplexWCF.Contract. ICallback。

Program:

using System;
using System.Collections.Generic;
using System.Text;
using Artech.DuplexWCF.Contract;
using System.ServiceModel;

namespace Artech.DuplexWCF.Client
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            DuplexChannelFactory
<ICalculator> channelFactory = new DuplexChannelFactory<ICalculator>(new InstanceContext(new CalculatorCallback()),"defaultEndpoint");
            ICalculator calculator 
= channelFactory.CreateChannel();
            Console.WriteLine(
"Try to invoke the Add method");

            
try
            
{
                calculator.Add(
12);
            }

            
catch (Exception ex)
            
{
                Console.WriteLine(
"An Exception is thrown!\n\t:Type:{0}\n\tMessage:{1}", ex.GetType(), ex.Message);
            }


            Console.Read();
        }

    }

}

在创建DuplexChannelFactory< ICalculator>中,指定了Callback Context Instance: 一个实现了Callback Contract的CalculatorCallback 对象。该对象在Service中通过OperationContext.Current.GetCallbackChannel<ICallback>()获得。

通过运行程序:

2. 基于Http的双向通讯V.S.基于TCP的双向通讯

由于Http和TCP在各自协议上的差异,他们实现双向通信的发式是不同的。

Http是一个应用层的协议,它的主要特征就是无连接和无状态(connectless & stateless )。它采用传统的Request/Reply的方式进行通信,Client发送Http Request请求Server的某个资源,Server端接收到该Http Request, 回发对应的Http Response。当Client端接收到对应的Response,该Connection会关闭。也就是说Client和Server的Connection仅仅维持在发送Request到接收到Response这一段时间内。同时,每次基于Http的 connection是相互独立,互不相干的,当前connection无法获得上一次connection的状态。为了保存调用的的状态信息,ASP.NET通过把状态信息保存在Server端的方式实现了对Session的支持,具体的做法是:ASP.NET为每个Session创建一个Unique ID,与之关联一个HttpSessionState对象,并把状态信息保存在内存中或者持久的存储介质(比如SQL Server)中。而WCF则采用另外的方式实现对Session的支持:每个Session关联到某个Service Instance上。

回到我们WCF双向通信的问题上,当Client调用Service之前,会有一个Endpoint在Client端被创建,用于监听Service端对它的Request。Client对Service的调用会建立一个Client到Server的Connection,当Service在执行操作过程中需要Callback对应的Client,实际上会建立另一个Service到Client的Http connection。虽然我们时候说WCF为支持双向通信提供Duplex Channel,实际上这个Duplex channel是由两个Request/Reply Channel组成的。

而对于TCP/IP簇中的传输层协议TCP,它则是一个基于Connection的协议,在正式进行数据传输的之前,必须要在Client和Server之后建立一个Connection,Connection的建立通过经典的“3次握手”来实现。TCP天生就具有Duplex的特性,也就是说当Connection被创建之后,从Client到Sever,和从Server到Client的数据传递都可以利用同一个Connection来实现。对于WCF中的双向通信,Client调用Service,Service Callback Client使用的都是同一个Connection、同一个Channel。所以基于TCP的Duplex Channel才是真正意义上的Duplex Channel。

WCF相关内容:
[原创]我的WCF之旅(1):创建一个简单的WCF程序
[原创]我的WCF之旅(2):Endpoint Overview
[原创]我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communication)
[原创]我的WCF之旅(4):WCF中的序列化(Serialization)- Part I
[原创]我的WCF之旅(4):WCF中的序列化(Serialization)- Part II
[原创]我的WCF之旅(5):Service Contract中的重载(Overloading)
[原创]我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案
[原创]我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承
[原创]我的WCF之旅(8):WCF中的Session和Instancing Management
[原创]我的WCF之旅(9):如何在WCF中使用tcpTrace来进行Soap Trace
[原创]我的WCF之旅(10): 如何在WCF进行Exception Handling
[原创]我的WCF之旅(11):再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯

[原创]我的WCF之旅(12):使用MSMQ进行Reliable Messaging
[原创]我的WCF之旅(13):创建基于MSMQ的Responsive Service

posted on 2007-06-18 18:32 Artech 阅读(7340) 评论(67)  编辑 收藏 网摘

评论

#1楼 2007-06-18 19:05 路人甲[未注册用户]

这个系列真的不过,LZ花了很多心思呀,希望首页多出现这样的文章。望LZ再接再厉。   回复  引用    

#2楼 2007-06-18 19:06 路人乙[未注册用户]

@路人甲
真是不错!
  回复  引用    

#3楼[楼主] 2007-06-18 19:08 Artech      

@路人甲
@路人乙
感谢两位路人的关注,我会继续这个系列。
  回复  引用  查看    

#4楼 2007-06-18 19:39 idior[未注册用户]

没错,这个问题是要注意的。
因为在http中使用duplex时会使用两个连接所以会产生安全方面的问题,而tcp就不存在了。
  回复  引用    

#5楼[楼主] 2007-06-18 20:25 Artech      

@idior
呵呵,很久没见你冒头了:)
  回复  引用  查看    

#6楼 2007-06-18 20:37 idior[未注册用户]

公司上cnblogs速度很慢,而且最近在翻译,所以很少冒泡了 :P   回复  引用    

#7楼 2007-06-18 20:46 Rexzhou[未注册用户]

相当不错,收藏你的Blog了,除了WCF,还有其他东东也可以看   回复  引用    

#8楼[楼主] 2007-06-18 20:59 Artech      

@Rexzhou
:)
  回复  引用  查看    

#9楼 2007-06-18 21:11 大坏蛋[未注册用户]

请问一下写的WCF客户端为什么夸了一个网络以后会 提示“服务器已拒绝客户端的凭据~~”   回复  引用    

#10楼[楼主] 2007-06-18 21:20 Artech      

@大坏蛋
我想是因为Authentication方面的原因,在默认的情况下,采用的是Windows Authentication(kerberos),一种基于Ticket的认证方式,只要用于Intranet。如果需要跨网络,你可能需要选择另外一种认证方式。不过具体原因,不是太确定。
  回复  引用  查看    

#11楼 2007-06-18 21:27 大坏蛋[未注册用户]

能说一个大概的方法吗!配置文件怎样写呢?能给个代码看一下吗?谢谢   回复  引用    

#12楼[楼主] 2007-06-18 21:39 Artech      

@大坏蛋
你可以参阅http://msdn2.microsoft.com/en-us/library/ms733836.aspx" target="_new">Selecting a Credential Type
  回复  引用  查看    

#13楼 2007-06-19 01:20 idior[未注册用户]

跨网络可以使用x509或WS-Trust+SAML Token
http://www.cnblogs.com/idior/archive/2006/05/16/354066.html
  回复  引用    

#14楼 2007-06-19 06:32 Jeffrey Zhao      

嗯,kerberos还必须用到AD   回复  引用  查看    

#15楼 2007-06-19 08:49 Anytao      

准备借着你的系列, 也玩玩WCF,专注与关注中。。。   回复  引用  查看    

#16楼[楼主] 2007-06-19 09:45 Artech      

@idior
@Jeffrey Zhao
谢谢两位的建议!
  回复  引用  查看    

#17楼[楼主] 2007-06-19 09:45 Artech      

@Anytao
Welcome to the world of WCF! 呵呵
  回复  引用  查看    

#18楼 2007-06-19 10:04 demohunter[未注册用户]

请问一个问题,我在客户端传一个contract类别的参数在server调用,但是却出错,是不是不能这样使用呢?例如:

[DataContract]
Class AContract
{
int aData;
[DataMember]
public int AData
{get;set;}
}


Server:
...
[OperationContract]
public void Add( AContract aContract )
{
//doSomething();
}

Client:
...
AContract aContract = new AContract();
aContract.AData = 2;
server.Add( aContract );//error....
  回复  引用    

#19楼[楼主] 2007-06-19 10:09 Artech      

@demohunter
DataContract是这样定义的,不知道你的具体出错信息是什么?
  回复  引用  查看    

#20楼 2007-06-19 10:31 demohunter[未注册用户]

在我的代码里面提示的是这样:

There was an error while trying to serialize parameter http://tempuri.org/:ob. The InnerException message was 'Type 'Observe_WPF_WCF_Charroom.IObserver.Observer' with data contract name 'Observer:http://schemas.datacontract.org/2004/07/Observe_WPF_WCF_Charroom.IObserver' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details
  回复  引用    

#21楼 2007-06-19 10:40 demohunter[未注册用户]

代码如下:
Client:

public partial class Window1 : Window
{



Service1Client server = new Service1Client();//代理类

public Window1()
{

try
{
InitializeComponent();

IObserver.IObserver ob = new IObserver.Observer();//一个Contract

server.Join("aaa", ob);
}
catch (Exception ex)
{ MessageBox.Show(ex.Message); }

}


}



public interface IObserver
{
[OperationContract]
void Update(string msg);
}


[DataContract]
public class Observer: IObserver
{

string text;
[DataMember]
public string Text
{
get { return this.text; }
set { this.text = value; }
}

string name;
[DataMember]
public string Name
{
get { return this.name; }
set { this.name = value; }
}

int type;
[DataMember]
public int Type
{
get { return this.type; }
set { this.type = value; }
}

public void Update(string msg)
{
if (this.type == 0)
{
this.text = this.name + "enter" + System.Environment.NewLine;

}
else if (this.type == 1)
{
this.text = this.name + " say :" + msg + System.Environment.NewLine;
}
else if (this.type == 2)
{

}
else if (this.type == 3)
{
this.text = this.name + "logout" + System.Environment.NewLine;

}
}




[ServiceContract(SessionMode = SessionMode.Required)]
[ServiceKnownType(typeof(IObserver.IObserver))]
public interface IService1
{

[OperationContract]
string[] Join(string name, Observe_WPF_WCF_Charroom.IObserver.IObserver ob);

[OperationContract]
void Say(string msg);

[OperationContract]
void Whisper(string to,string msg);

[OperationContract]
void Leave(string name);
}



public class Service1 : IService1
{

static Dictionary<string, IObserver.IObserver> list = new Dictionary<string, IObserver.IObserver>();


public Observe_WPF_WCF_Charroom.IObserver.IObserver Test()
{
Observer ob = new Observer();
ob.Text = "Test";
return ob;
}


public int Add()
{
IObserver.IObserver ob = new Observer();
(ob as Observer).Type = 2;
(ob as Observer).Type++;
return (ob as Observer).Type;
}

public string[] Join(string name, IObserver.IObserver ob)
{
list.Add(name, ob);
foreach (var ob1 in list)
{
(ob1.Value as IObserver.IObserver).Update(name + "Enter");
}
string[] list1 = new string[list.Count];
list.Keys.CopyTo(list1, 0);
return null;
}

public void Say(string msg)
{
//foreach (var ob in list)
//{
// (ob.Value as Observe_WPF_WCF_Charroom.IObserver.IObserver).Update(msg);
//}
}

public void Whisper(string to, string msg)
{
//list[to].Update(msg);
}

public void Leave(string name)
{
//list.Remove(name);
//foreach (var ob in list)
//{
// (ob.Value as Observe_WPF_WCF_Charroom.IObserver.IObserver).Update("");
//}
}
}
  回复  引用    

#22楼 2007-06-19 10:46 妖居      

@Anytao
@Artech
正在看你们二位的大做呢。
Anytao的[你必须知道的.NET]系列也是我非常喜欢的啊。
  回复  引用  查看    

#23楼[楼主] 2007-06-19 12:14 Artech      

@demohunter
[ServiceKnownType(typeof(IObserver.IObserver))] 改成[ServiceKnownType(typeof(Observer))] 试试看。
  回复  引用  查看    

#24楼[楼主] 2007-06-19 12:16 Artech      

@妖居
AnyTao的文章写得很深入,是学习的好素材。
  回复  引用  查看    

#25楼 2007-06-19 14:57 妖居      

@Artech
确实,你们二人一个是最新的技术研究,一个是深入的内核探索,确实让我受益匪浅啊。你是不是从国外的网站上学的WCF技术啊?我的E文不好,看那些技术文章一篇,头就大了。#_#而且此前看WPF的一些文章,MS自己写的很多都前后矛盾,或者不能运行。看来螃蟹还是很不容易吃的啊……
  回复  引用  查看    

#26楼[楼主] 2007-06-19 15:18 Artech      

@妖居
其实我不是一个新技术的狂热地追随者,我和AnyTao一样也喜欢研究CLR。现在WCF的中文资料很少,只有通过英文站点,MSDN是我学习资料的主要来源
  回复  引用  查看    

#27楼 2007-06-20 16:10 妖居      

@Artech
确实,现在WPF的资料还多一点,WCF就很少了,毕竟现在用.Net做企业及架构的就不是很多(至少没有Java多,我感觉。),用上WCF的就更少了。
其实当年.Net刚出的时候,也没有什么中文资料,M$给的资料少得可怜。

另外,方便的话,能不能加我MSN呢。我的地址是 farrio%vip.163.com。
  回复  引用  查看    

#28楼 2007-06-20 19:42 Bird[未注册用户]

To demohunter:
[DataMember]属性加到field上而不是property上
这里的话加到aData上去。
  回复  引用    

#29楼[楼主] 2007-06-20 20:37 Artech      

@Bird
@demohunter
DataMemberAttribute既可以用到Field也可以用到Property上,@demohunter得问题是DataContractAttribute是用到Observer而不是用到IObserver,所以[ServiceKnownType(typeof(IObserver.IObserver))] 要改成[ServiceKnownType(typeof(Observer))]
  回复  引用  查看    

#30楼[楼主] 2007-06-20 20:40 Artech      

@Bird
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited=false, AllowMultiple=false)]
public sealed class DataMemberAttribute : Attribute


  回复  引用  查看    

#31楼 2007-06-21 14:49 Leox      

Hi, Artech:
     谢谢你的这个系列作品,获益匪浅啊。
     如果可以的话,能不能写一篇关于采用MSMQ的Pub/Sub的文章。如果能有订阅管理控制的就更好了。
  回复  引用  查看    

#32楼[楼主] 2007-06-21 14:56 Artech      

@Leox
真的很巧,我现在正在准备“在WCF中使用MSMQ进行Reliable Messaging”的文章。
  回复  引用  查看    

#33楼 2007-06-21 17:26 winnie00      

这个哥哥写的太棒了,技术太好了,长的太帅了,太招人喜欢了,实在是米有太好的词了   回复  引用  查看    

#34楼[楼主] 2007-06-21 17:33 Artech      

@winnie00
熟归熟,你这样夸我我还是会脸红的:)
  回复  引用  查看    

#35楼 2007-06-22 08:42 Leox[未注册用户]

@Artech
期待你的<<在WCF中使用MSMQ进行Reliable Messaging>>.
加油啊。
  回复  引用    

#36楼 2007-06-22 18:27 cY2007.nET      

问问题的来了:
1.每个Session关联到某个Service Instance上,如果是一个用户一个Session,每个Session一个Service Instance,普通的服务器能承载多少个Service Instance。
2.WCF中,服务端是否是并发处理客户的请求(不论是TCP还是HTTP模式)?
3.多客户端(超过1000个)的应用程序,WCF服务器端应如何设计。

因为要设计的软件同时在线的人数可能超过1000人,而我是首次接触WCF和客户端-服务器端程序,MSDN也看了不少,但是还是理不出头绪,希望博主和各位大侠给点参考资料,链接就成。
  回复  引用  查看    

#37楼[楼主] 2007-06-22 20:36 Artech      

@cY2007.nET
1. 你的第一个问题,我确实没有一个量化的概念。
2. 多个客户请求可以并发操作,你可以通过设置ConcurrencyMode进行相关的设置。
3. 象你的说得这种同时处理多客户端的情况,个人觉得不用使用Session,最好使用PerCall的Instancing方式。
  回复  引用  查看    

#38楼 2007-09-14 16:49 虫子congch_qm@faw.com.cn[未注册用户]

请教高手,我做了的wcf 应用是host 到iis 上的,在做的一个服务方法,更形数据;在调用方法的数据量比较少时没有问题;eg 6列30几条数据没问题;6列360条就有问题了包的错误是
The remote server returned an unexpected response: (400 ) Bad Request.
先感谢先;我的邮箱congch_qm@faw.com.cn
  回复  引用    

#39楼[楼主] 2007-09-14 17:46 Artech      

@虫子congch_qm@faw.com.cn
该不会你的Response Soap太大了,超出Soap允许的范围吧。
  回复  引用  查看    

#40楼 2007-10-19 09:27 路人丙[未注册用户]

感谢上天赐于我们这么多好人   回复  引用    

#41楼[楼主] 2007-10-19 10:07 Artech      

@路人丙
^_^
  回复  引用  查看    

#42楼 2008-01-16 11:38 好人一生平安[未注册用户]

看了这系列的教程,真是受益非浅啊
感谢博主!
  回复  引用    

#43楼 2008-03-03 09:48 人民币[未注册用户]

非常期待楼主关于wcf security方面的文章   回复  引用    

#44楼 2008-03-05 10:04 xie[未注册用户]

从楼主的文章开始入手WCF的,看后获益匪浅,多谢楼主;

我安装楼主提供的代码允许部署后,在另一台机器上却访问不了,我用的不是IIS托管; 感觉是权限的问题,因为本机访问是完全没有问题的,其他机器上能看到有这个服务 但是Channel连接失败;还望楼主不吝赐教;有解决代码就更好了,麻烦发我一份;我的邮箱kingxiekang@163.com
  回复  引用    

#45楼 2008-04-19 21:36 BAsil      

很好的文章   回复  引用  查看    

#46楼 2008-05-26 13:59 阿滨       

回调接口是否支持继承?
public interface ICallback:IUpDataCallBack
{
........
}


[ServiceContract(CallbackContract = typeof(ICallback))]
  回复  引用  查看    

#47楼 2008-06-10 23:15 安德尔斯[未注册用户]

局域网内 net:tcp 连接失败是什么原因
  回复  引用    

#48楼[楼主] 2008-06-12 10:02 Artech      

@安德尔斯
这个问题就不好回答了,可能是网络问题, 比如Firewall, 防毒软件, ...
  回复  引用  查看    

#49楼[楼主] 2008-06-12 10:04 Artech      

@阿滨
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, Inherited=false, AllowMultiple=false)]
public sealed class ServiceContractAttribute : Attribute

ServiceContractAttribute 不能被继承。
  回复  引用  查看    

#50楼 2008-09-14 00:09 Victor.Woo[未注册用户]

基于dualtcp等,是否能实现“反向调用”?即:
内网client连接公网server,server调用client的服务。
注意此时client若公开终结点,server通过回调是连接不上它的,因为client的ip是内网的(这样理解有没有错?)
如果理解没有错的话,如何实现该反向调用?
谢谢!
  回复  引用    

#51楼[楼主] 2008-09-14 17:15 Artech      

@Victor.Woo
Duplex一般应用于局域网,不太适合Internet。主要是防火墙的问题。
  回复  引用  查看    

#52楼 2008-10-17 12:01 摄狼      

楼主,你好,我现在用silverlight和wcf做一个聊天程序,程序启动没问题,开始可以聊天,但是如果我过几分钟不去管他,然后在开始进行聊天,就会出现 “通信对象 System.ServiceModel.Channels.ClientPollingDuplexSessionChannel 无法用于通信 因为其处于出错状态”.不知道为什么?   回复  引用  查看    

#53楼 2009-02-25 19:46 双工[未注册用户]

--引用--------------------------------------------------
Artech: @Victor.Woo
Duplex一般应用于局域网,不太适合Internet。主要是防火墙的问题。
--------------------------------------------------------
请问在Internet上面,进行双工通信怎么实现呢?
  回复  引用    

#54楼[楼主] 2009-03-02 16:11 Artech      

@双工
Internet上 基本上不会使用双工通信
  回复  引用  查看    

#55楼 2009-03-02 18:16 WCFLearning[未注册用户]

谢谢LZ的辛勤劳动,实在是太用帮助!
请教一个问题,讨论基于HTTP和TCP的双向通讯的差异能否举例说一下在实际中的应用呢?
  回复  引用    

#56楼 2009-03-02 22:17 goldenlily

再请问一下,要安装什么才在新建项目web下有WCF Service Application模板呢?我的只有WCF Service Library?   回复  引用    

#57楼[楼主] 2009-03-03 08:06 Artech      

@WCFLearning

[原创]WCF后续之旅(9):通过WCF的双向通信实现Session管理


  回复  引用  查看    

#58楼[楼主] 2009-03-03 08:08 Artech      

--引用--------------------------------------------------
goldenlily: 再请问一下,要安装什么才在新建项目web下有WCF Service Application模板呢?我的只有WCF Service Library?
--------------------------------------------------------
VS2008默认就有, 2005好像没有见着!
  回复  引用  查看    

#59楼 2009-03-03 11:13 WCFLearning[未注册用户]

回复真及时,感谢您的帮助!继续学习中!   回复  引用    

#60楼 2009-03-06 03:02 Sean153250280[未注册用户]

博主好,我是新手。想请教一下,BS架构下可以实现WCF的双向通信吗?可以的话怎么做呢?有参考文章或示例吗?谢谢!   回复  引用    

#61楼 2009-05-01 13:27 jiuyuong[未注册用户]

非常好的文章   回复  引用    

#62楼 2009-05-31 00:22 cnly[未注册用户]

该系列文章真是不错!   回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 788071




相关文章:

相关链接: