现在的位置: 首页 > 综合 > 正文

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

2013年10月18日 ⁄ 综合 ⁄ 共 5005字 ⁄ 字号 评论关闭

目标:实现一个简单的聊天室。本文实现的聊天室仅出于演示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("请输入用户名:rn" );
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("请输入聊天内容:rn" );
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,欢迎关注开源技术应用的朋友一起交流进步。
项目下载:
sgsoft 发表于:2007.05.07 17:52 ::分类: ( 


抱歉!评论已关闭.