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,欢迎关注开源技术应用的朋友一起交流进步。
项目下载:



本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/sgsoft/archive/2007/05/07/738011.html,如需转载请自行联系原作者
相关文章
|
安全 前端开发
FastAPI(56)- 使用 Websocket 打造一个迷你聊天室 (上)
FastAPI(56)- 使用 Websocket 打造一个迷你聊天室 (上)
439 0
FastAPI(56)- 使用 Websocket 打造一个迷你聊天室 (上)
|
4月前
|
存储 前端开发 Go
golang怎么搭建Websocket聊天室服务端
连接的添加和移除 添加连接: 当一个新的WebSocket连接建立时,服务器需要将这个连接添加到全局的连接列表中。多个连接可能同时建立,从而导致多个并发操作试图修改连接列表。 移除连接: 当一个WebSocket连接断开时,服务器需要将这个连接从全局的连接列表中移除。如果多个连接同时断开,可能会导致并发修改连接列表。
|
设计模式 前端开发 Java
用WebSocket实现一个简易的群聊功能,so easy
本文主要来讲解如何使用WebSocket来实现一个简易的群聊功能。
|
消息中间件 网络协议 Ubuntu
Robot OS网络通信MQTT实战
最近开发的机器人操作系统ROS基于Android,在里面做一些深度定制,其中运动控制与Server的交互需要双向通道,经过权衡和讨论我们最终选用MQTT作为长连接通信方案。
263 0
Robot OS网络通信MQTT实战
|
Go 调度
Go实现简易聊天室(群聊)
Go实现简易聊天室(群聊)
284 0
Go实现简易聊天室(群聊)
|
JSON 物联网 开发工具
阿里云物联网.NETCore客户端|CZGL.AliloTClient:3.订阅To pic与响应Topic
阿里云物联网.NETCore客户端|CZGL.AliloTClient:3.订阅To pic与响应Topic
329 15
EMQ
|
物联网 Linux 开发者
MQTT X Newsletter 2022-06 | v1.8.0 发布,新增 MQTT CLI 和 MQTT WebSocket 工具
本月,MQTT X 发布了最新的 1.8.0 版本,新增了 MQTT CLI 和 MQTT WebSocket 客户端工具,支持在终端命令行或桌面浏览器上快速完成对 MQTT 的连接测试。
EMQ
242 0
MQTT X Newsletter 2022-06 | v1.8.0 发布,新增 MQTT CLI 和 MQTT WebSocket 工具
|
移动开发 前端开发 网络协议
【go,聊天室】认识 WebSocket
【go,聊天室】认识 WebSocket
605 0
【go,聊天室】认识 WebSocket
|
Web App开发 调度 ice
WebRTC ICE 状态与提名处理
大家都知道奥斯卡有提名,其实在 WebRTC 的 ICE 中也有提名,有常规的提名,也有激进的提名,而且提名的候选人不一定是最优秀的候选人喔,本文就带你一探其中玄妙。文章内容主要描述 RFC 5245 中 ICE 相关的状态和 ICE 提名机制,并结合 libnice(0.14) 版本进行分析。
WebRTC ICE 状态与提名处理