海鸥航迹

学习之笔记,好文之收集。

导航

ICE专题:实现简单的聊天室(一)

目标:实现一个简单的聊天室。本文实现的聊天室仅出于演示ICE的多播功能,即由一个Client发送的消息,广播至注册的其他Client上。以后的系列文章,将逐步完善这个例子,使其成为一个现实意义上可用的聊天室软件。

Slice定义:

 

module ChatSpaceDef
{
       //回调函数接口,就是客户端传递给服务器,服务器接收到的一个方法代理签名
       interface CallBack
       {
              void GetInput(string content);
       };
       //在线列表
       dictionary<string,CallBack *> CacheMap;
       //聊天室功能列表
       interface ChatSpace
       {
              bool Register(string name);//注册
              void SetInput(string content);//发送消息
              void Unregister();//退出
              void SetupCallback(CallBack * cp);//设置回调
       };

};

运行命令:
slice2cs --output-dir generated *.ice
此命令将生成Client和Server都要使用的应用程序骨架ChatSpaceDef.cs文件。要了解该文件的类的所有信息,
请参考Ice用户手册

定义服务器端

对服务器而言,实现ChatSpaceDisp_抽象基类即可,换言之,需要实现:
 bool Register(string name);//注册
 void SetInput(string content);//发送消息
 void Unregister();//退出
 void SetupCallback(CallBack * cp);//设置回调

这4个方法。代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using ChatSpaceDef;

namespace ChatSpace
{
    public sealed class ChatSpaceI : ChatSpaceDisp_
    {
        public override bool Register(string name, Ice.Current current__)
        {
            Console.WriteLine("验证 {0} 是否被注册了!", name);
            return !m_cache_map.Contains(name);
        }

        public override void SetInput(string content, Ice.Current current__)
        {
       //向其他人广播消息 string user_name = current__.ctx["user_name"]; foreach (string key in m_cache_map.Keys) { if (key == user_name) { continue; } m_cache_map[key].GetInput(content, current__.ctx); } } public override void Unregister(Ice.Current current__) { if (current__.ctx["user_name"] != null) { m_cache_map.Remove(current__.ctx["user_name"]); Console.WriteLine("注销{0}成功", current__.ctx["user_name"]); } } public override void SetupCallback(CallBackPrx cp, Ice.Current current__) { if (current__ != null && current__.ctx["user_name"] != null) { string user_name = current__.ctx["user_name"]; Console.WriteLine("上下文是user_name={0}", user_name); m_cache_map.Add(user_name, cp); } else { throw new Exception("上下文错误!"); } } CacheMap m_cache_map = new CacheMap(); } }
上述代码都非常简单易懂,需要解释的是:Ice.Current表示调用者携带的上下文信息,这是Ice的内部机制,你可以在
方法调用上,通过Context对象携带其他与调用相关的信息,注意,它不是方法调用的参数,它是Client和Server在网络
中网络环境下传递信息的一种载体。

定义Server端配置config.server:
Callback.Server.Endpoints=tcp -p 12345:udp -p 12345

#
# Warn about connection exceptions
#
Ice.Warn.Connections=1

#
# Network Tracing
#
# 0 = no network tracing
# 1 = trace connection establishment and closure
# 2 = like 1, but more detailed
# 3 = like 2, but also trace data transfer
#
#Ice.Trace.Network=1

#
# Protocol Tracing
#
# 0 = no protocol tracing
# 1 = trace protocol messages
#
#Ice.Trace.Protocol=1

#
# Security Tracing
#
# 0 = no security tracing
# 1 = trace messages
#
#IceSSL.Trace.Security=1

server端的主程序非常简单Server.cs:
using System;
using System.Collections.Generic;
using System.Text;

namespace ChatSpace
{
    public class Server : Ice.Application
    {
        public override int run(string[] args)
        {
            Ice.ObjectAdapter adapter = communicator().createObjectAdapter("Callback.Server");           
            adapter.add(new ChatSpaceI(), communicator().stringToIdentity("callback"));
            adapter.activate();
            communicator().waitForShutdown();
            return 0;
        }

        public static void Main(string[] args)
        {
            Server app = new Server();
            int status = app.main(args, "config.server");
            if (status != 0)
            {
                System.Environment.Exit(status);
            }
        }
    }
}
 
 

 

定义客户端

对客户端而言,只需要实现回调方法即可了CallBackI.cs。

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

using ChatSpaceDef;

namespace Client
{
    public sealed class CallBackI:CallBackDisp_
    {
        public override void GetInput(string content, Ice.Current current__)
        {
            System.Console.WriteLine("服务器传递过来的信息:{0} Say:{1}",current__.ctx["user_name"],content);
        }
    }
}
客户端主程序Client.cs:
 
using System;
using System.Collections.Generic;
using System.Text;

using ChatSpaceDef;

namespace Client
{
    class Client : Ice.Application
    {
        static void Main(string[] args)
        {
            Client app = new Client();
            int status = app.main(args, "config.client");
            if (status != 0)
            {
                System.Environment.Exit(status);
            }
        }

        public override int run(string[] args)
        {
            ChatSpacePrx spacePrx = ChatSpacePrxHelper.
                checkedCast(communicator().propertyToProxy("Callback.CallbackServer"));

            if (spacePrx == null)
            {
                System.Console.WriteLine("网络配置无效!");
                return 1;
            }
            System.Console.WriteLine("请输入用户名:\r\n");
            string user_name = Console.ReadLine();

            if (spacePrx.Register(user_name) == false)
            {
                System.Console.WriteLine("该用户名已被注册!");
                return 1;
            }
            Ice.ObjectAdapter adapter = communicator().createObjectAdapter("Callback.Client");
            adapter.add(new CallBackI(), communicator().stringToIdentity("callbackReceiver"));
            adapter.activate();
                      
            
            CallBackPrx callbackPrx = CallBackPrxHelper.uncheckedCast(adapter.createProxy(communicator().stringToIdentity("callbackReceiver")));
            Ice.Context ctx = new Ice.Context();
            ctx.Add("user_name", user_name);

            spacePrx.SetupCallback(callbackPrx,ctx);

            System.Console.WriteLine("请输入聊天内容:\r\n");
            string content = "";
            while (content != "X")            
            {
                content = System.Console.ReadLine();
                spacePrx.SetInput(content,ctx);                
            }
            spacePrx.Unregister(ctx);

            return 0;

        }
    }
}
客户端配置文件:

Callback.CallbackServer=callback:tcp -p 12345:udp -p 12345
Callback.Client.Endpoints=tcp:udp

#
# Warn about connection exceptions
#
Ice.Warn.Connections=1

#
# Network Tracing
#
# 0 = no network tracing
# 1 = trace connection establishment and closure
# 2 = like 1, but more detailed
# 3 = like 2, but also trace data transfer
#
#Ice.Trace.Network=1

#
# Protocol Tracing
#
# 0 = no protocol tracing
# 1 = trace protocol messages
#
#Ice.Trace.Protocol=1

#
# Security Tracing
#
# 0 = no security tracing
# 1 = trace messages
#
#IceSSL.Trace.Security=1


至此,一个多播聊天室就此完成。

编译运行:

 
ICE,SQLite,JasperReport……开源技术讨论群:25935569,欢迎关注开源技术应用的朋友一起交流进步。
项目下载:项目文件 ICEChatSpace

posted on 2007-05-07 16:21  海天一鸥  阅读(6839)  评论(9编辑  收藏  举报