WCF的若干问题,恳请各位近来指教一二!

BATTLERxANGE 2009-12-31 06:29:08
1:如何记录已经建立连接的用户?我需要建立一个LIST,将已经建立连接的用户存放到这个LIST中,以便知道有多少连入用户和接下来进行某些操作。我没有找到关于建立连接的事件……
2:关于回调,如何做到随时像某个用户进行回调操作?也就是发消息给用户?我知道现在回调只能在用户调用了服务的方法后,在方法里面进行回调,如果我想在若干秒以后,将TEXTBOX1中的字符串发给用户的话,该怎么办?如果不是在用户调用的方法内回调的话,会得到一个“未将对象引用设置到对象的实例”的异常!此时的OperationContext.Current对象为NULL,也就是丢失了服务的上下文。
3:如果定义一个全局变量?启动了服务以后,根据会话模式,好象所有的变量都成了会话内部的变量了。比如我设置会话模式为InstanceContextMode.PerSession,那么所有的会话都可以使用他们自己的变量,也就像线程中的变量一样各自是各自的并不会互受影响。但是我现在假如需要定义一个全局的,该如何定义呢?例如我想定义一个全局的LIST<T>变量,来存放已经建立连接的用户,还有一些其他的信息等。

我是想使用比较成熟的模型来建立C/S程序,当然不是那种客户端-数据库的那种,这样的直接连数据库没任何安全性,也不想将数据库直接暴露在外,我想建立的是客户端-服务端-数据库这种构架!虽然说可以使用SOCKET,但是其很难控制,做做聊天室等简单的不用说了谁都会,没有技术含量。但是如果要传递表,结构等一些数据会变的很麻烦,可以序列化,但是很难控制一些诸如“粘包”等问题!
是我自己想错了WCF并不适合设计这种构架,还是说有其他的什么解决方案呢?请各位指教一二!!谢谢!
...全文
228 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
sewsew 2012-07-13
  • 打赏
  • 举报
回复
简而言之就是对WCF服务的实现的类在构造的时候,把OperationContext.Current存起来,将来访问客户端的时候用来GetCallbackChannel.
InstanceContextMode 要使用PerSession或者Single
BATTLERxANGE 2010-01-01
  • 打赏
  • 举报
回复
依然没有人理会T T
BATTLERxANGE 2009-12-31
  • 打赏
  • 举报
回复
怪不得现在CSDM不景气呢!容易的问题一大堆人回答,这种问题根本没人理会,为什么呢?因为有了5,6L这样的人,唉!
wuyq11 2009-12-31
  • 打赏
  • 举报
回复
WCF除了支持经典的请求/应答模式意外,还提供了对单向操作、双向回调操作模式的支持
WCF
dqw120 2009-12-31
  • 打赏
  • 举报
回复
1.定义接口
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IWriteLogCallback))]
public interface ILogService
{
[OperationContract(IsInitiating = true, IsTerminating = false)]
void Write(string logMsg);

[OperationContract(IsInitiating = true, IsTerminating = false)]
void RegisterListener();

[OperationContract(IsInitiating = false, IsTerminating = false)]
void UnregisterListener();
}

[ServiceContract]
public interface IWriteLogCallback
{
[OperationContract(IsOneWay = true)]
void OnWriteLog(string logMsg);
}
为了简单举了一个写日志的例子, Write(string logMsg)就是写入日志的方法,参数logMsg是需要写入的日志信息。当客户单没有调用RegisterListener()订阅事件的时候,是不会收到写日志的事件通知的,相应的要获得写日志的事件通知,就需要调用RegisterListener()方法。如果要取消订阅就调用UnregisterListener()方法。写日志的功能和事件的订阅功能是分开的。

2.服务实现
[ServiceBehavior(
IncludeExceptionDetailInFaults = true,
InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
class LogService:ILogService
{
public LogService()
{
Trace.WriteLine("Create LogService Instance.");
}

Dictionary<string, OperationContext> listeners = new Dictionary<string, OperationContext>();

private void BroadCast(string logMsg)
{
List<string> errorClints = new List<string>();

foreach (KeyValuePair<string, OperationContext> listener in listeners)
{
try
{
listener.Value.GetCallbackChannel<IWriteLogCallback>().OnWriteLog(logMsg);
}
catch (System.Exception e)
{
errorClints.Add(listener.Key);
Trace.WriteLine("BROAD EVENT ERROR:" + e.Message);
}
}

foreach (string id in errorClints)
{
listeners.Remove(id);
}
}

#region ILogService 成员

public void Write(string logMsg)
{
Trace.WriteLine("Write LOG:"+logMsg);
BroadCast(logMsg);
}

public void RegisterListener()
{
listeners.Add(OperationContext.Current.SessionId, OperationContext.Current);

Trace.WriteLine("SessionID:" + OperationContext.Current.SessionId);
Trace.WriteLine("Register listener. Client Count:" + listeners.Count.ToString());
}

public void UnregisterListener()
{
listeners.Remove(OperationContext.Current.SessionId);
Trace.WriteLine("SessionID:" + OperationContext.Current.SessionId);
Trace.WriteLine("Unregister listener. Client Count:" + listeners.Count.ToString());
}

#endregion
} Dictionary<string, OperationContext> listeners包含了所有的事件订阅者。发布事件的时候,如果调用订阅者的回调函数失败,就把该订阅者从listeners移除。代码很简单,就不多说了。
3.客户端访问
定义回调的客户端:
class LogClient:IWriteLogCallback
{
#region IWriteLogCallback 成员

public void OnWriteLog(string logMsg)
{
Trace.WriteLine("RECV LOG EVENT:" + logMsg);
}

#endregion
}
然后在程序中使用它:
class Program
{
static void Main(string[] args)
{
Trace.Listeners.Add(new ConsoleTraceListener());
LogClient client = new LogClient();
ILogService service = DuplexChannelFactory<ILogService>.CreateChannel(client,
new WSDualHttpBinding(), new EndpointAddress("http://localhost:8888/log"));

//订阅消息
service.RegisterListener();
service.Write("Client start");

Console.WriteLine("Press enter key to exit.");
Console.ReadLine();

service.UnregisterListener();
}
BATTLERxANGE 2009-12-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 hyblusea 的回复:]
WCF中使用观察者模式实现事件通知
http://www.cnblogs.com/dyj057/archive/2008/04/25/1171352.html
[/Quote]
谢谢,确实可以解决第一、二问题。但是那文章最后也说到了“ 这里使用的是单实例的服务,所以需要进行多进程访问的保护,才能实际使用。”,关于这个我不知道该如何来申明一个全局静态变量,我需要将会话设置成InstanceContextMode.PerSession模式。
不过为此我学到了该如何保存已连接的用户,非常感谢!
BATTLERxANGE 2009-12-31
  • 打赏
  • 举报
回复
呵呵sp1234大大一直在黑设计模式一书呢,只看过一点,确实没见过有使用过“事件”。不过我还太菜就不评论这个了。
还想请教大大给一些指点,非常感谢!
  • 打赏
  • 举报
回复
事件通知就事件通知呗,WCF的事件通知是从《设计模式》上抄袭来的那种形式吗?如果不是何必要扯上设计模式里发明的特殊名词?
hyblusea 2009-12-31
  • 打赏
  • 举报
回复
WCF中使用观察者模式实现事件通知
http://www.cnblogs.com/dyj057/archive/2008/04/25/1171352.html

110,552

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧