1. Slice接口
Slice是Ice使用的接口定义语言。有了它,你可以给应用程序定义客户端—服务器协议,包括所有接口、操作、参数、数据类型和异常。如果你熟悉诸如C++、Java或C#等编程语言,则Slice语法将很快的熟知起来。
下面的部分介绍推拉模型的Slice接口。如果你只想了解特定编程语言的Ice,则应该查看C++、JavaScript、Java或C#的推式模型以及PHP的拉式模型。
1.1. 推模型
推客户端必须实现以下接口:
module Chat
{
interface ChatRoomCallback
{
void init(Ice::StringSeq users);
void send(long timestamp, string name, string message);
void join(long timestamp, string name);
void leave(long timestamp, string name);
}
}
当客户端加入聊天室时,服务端调用init方法;该方法提供房间中的用户列表作为字符串序列。服务端调用send方法来通知客户有新消息,包括时间戳和发送者的名字。最后,服务器分别在用户加入或离开聊天室时调用join和leave方法。
Glacier2提供了一个回话方式,我们可以扩展我们的推送模式。服务器端Slice接口来自Glacier2::Session接口:
module Chat
{
interface ChatSession extends Glacier2::Session
{
void setCallback(ChatRoomCallback* cb);
long send(string message) throws InvalidMessageException;
}
}
客户端通过建立一个回话并用setCallback来传递它的回调对象代理,从而加入聊天室。客户端使用send向当前聊天室中的所有用户发送新消息。最后,在终止之前,客户端调用destroy(从Glacier2::Session继承)离开房间并销毁会话。
1.2. 拉模型
我们的拉模式使用Slice的类来定义在聊天室中发生的事件。ChatRoomEvent是所有事件的基类,包含时间戳和用户名。ChatRoomEvent的子类回应加入房间的用户,离开房间并发送消息。要确定发生了哪种类型的事件,客户端必须执行语言特定的向下演播(down-cast)。
module PollingChat
{
class ChatRoomEvent
{
long timestamp;
string name;
}
sequence<ChatRoomEvent> ChatRoomEventSeq;
class UserJoinedEvent extends ChatRoomEvent {}
class UserLeftEvent extends ChatRoomEvent {}
class MessageEvent extends ChatRoomEvent
{
string message;
}
}
我们不使用Glacier2作为拉模型,因此我们需要创建自己的会话方式:
module PollingChat
{
interface PollingChatSession
{
Ice::StringSeq getInitialUsers();
ChatRoomEventSeq getUpdates();
long send(string message) throws Chat::InvalidMessageException;
void destroy();
}
interface PollingChatSessionFactory
{
PollingChatSession* create(string name, string password)
throws CannotCreateSessionException;
}
}
拉客户端通过在factory上调用create来创建一个会话。该方法接受用户名和密码(我们的实现接受任何组合),并向会话对象返回一个代理。创建会话后,客户端调用getInitialUsers获取当前在聊天室中的用户列表,然后定期调用getUpdates来接收事件。send方法允许客户端发布新的消息,destroy终止客户端的会话。