软件频道>程序开发>JavaVBVCDelphiC/C++Web开发微软专栏移动数据库程序人生软件工程|开发客
您现在的位置: 天极网 > 开发频道 > 使用服务器端Toolkit扩展Sametime服务器的功能
全文

使用服务器端Toolkit扩展Sametime服务器的功能

2008-05-08 07:00作者:刘欣 常红平出处:天极网责任编辑:McLaren

  本篇文章将把重点转移到服务器端,主要介绍服务器端 Java Toolkit 的使用方法和重要的 API,并带领读者循序渐进的开发出一个简单的猜拳游戏。

  Sametime 服务器端 toolkit 介绍

  下表列出了服务器端的各种 toolkit,在版本 7.0 前这三个 API 是分开打包的,而版本 7.5 将这三个 API 合了在一起。

  版本用途和使用环境

  Sametime Community Server toolkit一套 Java 的 API,用来加强 Sametime 的功能和服务

  Sametime Directory and Database Access toolkit一套 C 的 API,用来定制对已存在的 Sametime 目录服务器或数据库的访问

  Sametime Telephony toolkit用来集成电话会议功能

  其中本文 Community Server toolkit 是最为常用的工具包。本文将只对版本 7.0 Community Server toolkit 进行介绍。下文中如果没有特殊说明,当提到 toolkit 时,均是指版本 7.0 Community Server toolkit。

  Sametime community Server toolkit 简介

  Sametime community toolkit 是 Sametime java client toolkit 的超集,它提出了一个新的概念: Server Application,表示在 Sametime community 中的一个功能或者服务。 Sametime 服务器本身的绝大部分功能都是由 Server Application 构成的。

  通过 Community Server Toolkit,开发人员能够开发满足特定需求的 Server Application, 注册到 Sametime 社区中,成为其中的“一等公民”,从而对外提供服务。

  Sametime community 体系结构

  一个 Sametime community 包括如下四种 community 成员:

  客户端(Clients):是一个以用户身份使用 TCP/IP 协议登录到 community 的程序。客户端有用户界面。

  多路复用器(Multiplexers):通过集中 I/O 访问提高 Sametime 的稳定性。多路复用器对于客户端是透明的。

  Community 集线器(Community Hub):是 Sametime community 的核心,它负责管理 community 的参与者(客户端,多路复用器和服务器应用程序),在各个 community 成员间路由信息,并负责通知事件的接收者。Community 集线器可以有一个或多个。

  服务器应用程序(Server Application):Sametime 的绝大多数功能都是由服务器应用程序提供的,其它少部分由 Sametime 内核组件提供。服务器应用程序使用 TCP/IP 协议直接连接到 Community 集线器。

  下面是一个 Sametime community 的结构图:

  图1:Sametime community 体系结构

  图1:Sametime community 体系结构

  Community 中的信息路由依赖于一种称为信道(Channel)的虚拟连接。一条信道可能会跨越多个 TCP/IP 连接。例如下面的例子,该信道跨越了 4 个 TCP/IP 连接。

  图2:一个跨越 4 个 TCP/IP 连接的信道

  图2:一个跨越 4 个 TCP/IP 连接的信道

  服务器应用程序实现了 Community 服务器的各项功能。一个服务器应用程序可以是一个或多个服务(Service)的容器。而一个服务也可以被包含在一个或多个服务器应用程序中。Sametime Community 中内置的主要服务器应用程序包括:

  配置(Configuration):定时从 Sametime 配置数据库读取配置信息并且分发到相应 Community 参与者。

  用户感知(Awareness 或 Buddy List):感知 Community 中的其他用户的状态。

  认证(Authentication):用户认证是针对 community directory 实现的。 用户认证可以有多种方式

  目录(Directory):提供 Sametime 目录浏览功能,通常用来解析或查找用户。

  用户数据存储(User Storage):负责在服务器上存储用户相关数据,如用户通用属性和私有属性。

  日志(Logging):负责将 Community 服务器中的活动信息记入日志。包括普通的服务器活动和用户间的交谈内容。

  空间(Places):提供空间级(place-based)的用户感知和交流工具。

  在线目录(Online directory):负责在整个 community 的多个 community hub 间中维护一个一致的用户状态快照(如谁当前在线,登录到哪个 hub,哪个 place 等)。

  这些服务器应用程序相互配合构成了 Sametime 服务器的主要功能。而用户在使用 Sametime 客户端应用程序时不会感觉到它们的存在。如果要开发自己的服务器应用程序,我们需要熟悉 toolkit 中的各种服务。

  Sametime Community toolkit 提供的主要服务包括:

  服务器应用程序服务(Server application service):使用 toolkit 编写任何服务器应用程序都要用到这个服务。我们可以通过该服务以一个服务器应用程序的身份登录到 Sametime 服务器,注册或注销服务类型。

  信道服务(Channel service):提供通过 Sametime 交流的协议。一个服务器应用程序在 Sametime 服务器上注册了它的服务类型后,Sametime 服务器会把所有打开信道的申请转发到该服务器应用程序。一但信道被打开后,服务器应用程序就可以使用该信道与其他客户端交流了。

  Community 事件服务(Community events service):当事件发生时,负责通知用户或服务器应用程序。这些事件包括:

  用户登录

  登录失败

  服务启动或停止

  用户状态变化

  用户私有列表变化

  用户上线或下线

  用户存储(storage)变化

  通用感知服务(General awareness service):用来设置或删除 Sametime Server 的一些属性(如是否支持音频、视频等)。

  空间管理服务(Places admin service):用来管理空间服务器应用程序。如创建空间,管理空间的特性等。

  空间活动服务(Places activity service):用来编写 Sametime 空间的活动提供者(activity provider)。活动(activity)是一个在空间中运行的程序,该程序是空间中所有成员都可见的。活动提供者可以执行一系列的任务,如监视空间中消息,控制用户等。

  服务器应用程序存储服务(Server application storage service):用来把用户相关的信息作为属性直接存储到Sametime服务器中。我们自己的服务器应用程序可以使用这个服务存取标准的 Sametime 属性或应用程序特定的属性。

  轻量级登录服务(Light login service):允许一个多路复用器应用程序(MUX application)向服务器同时传输多个连接。多路复用器应用程序可以作为一个客户端网关来实现轻量级登录。

  服务器应用程序证明服务(Server application token service):用来生成一个作为用户登录到 Sametime 的证明(token)。这个服务在一个应用程序想要一个用户身份登录时非常有用。

  开发 Sametime 服务器端应用程序

  限于篇幅,本文不可能涉及 Sametime Community toolkit 中的所有功能。本文将随着介绍服务器 toolkit 中的最重要服务带领读者完成一个简单的猜拳游戏(finger-guessing game)。有兴趣的读者可以自行阅读本文列举的参考资料和服务器端 toolkit 自带的其他示例程序。

  这个猜拳游戏所涉及到的服务包括:

  服务器应用程序服务

  Community事件服务

  空间管理服务

  空间活动服务

  该程序客户端界面如下图所示。

  图3:猜拳游戏客户端界面

  图3:猜拳游戏客户端界面

  服务器端程序的界面比较简单,只提供一个“Stop Service”按钮,通过它可以删除在游戏中创建的空间。

  我们先来看看这个游戏程序的功能:

  玩家登录以后,可以从游戏桌 (desk0,desk1,desk2) 中任选一个,点击“Enter”进入该游戏桌,此时会有 3 种情况:

  该游戏桌已经坐满了,当前玩家将无法进入,只能选择其他的游戏桌;

  该游戏桌已经有领一个玩家在等待(猜拳游戏需要两个游戏者), 那么游戏立刻开始;

  该游戏桌还没有任何人,此时当前玩家需要等待其他玩家;

  游戏开始后,用户可以点击“Stone”,“Scissor”,“Paper”来猜拳,另一玩家出拳后,游戏的服务器端会给出胜负判断,把消息显示在下面的面板中。 一轮游戏结束。下一轮游戏开始。

  玩家可以随时点击“Leave”离开当前的游戏桌,此时游戏随之中止。

  在下面的章节中,本文将使用 Sametime Community Toolkit 中的相关服务来完成给猜拳游戏,为了便于读者理解这些服务的使用,本文中的代码只是从程序中摘取的一些片断并做了少许修改,完整的代码可以在参考资料中下载。

  一、概述

  猜拳游戏分为服务器端(FGServer)和客户端(FGClient)两个部分,分别使用了 Server toolkit 和 client toolkit,其中 FGServer 主要完成创建虚拟的游戏桌、检测用户事件、维持游戏桌的状态、判断游戏胜负等功能。FGClient 主要是完成进入游戏桌、在游戏桌中玩游戏等功能。

  FGServer 的功能:

  创建游戏桌

  猜拳游戏使用 Place 来模拟游戏桌,程序初始化时会使用 PlacesAdminService 创建 3 个缺省的 Place 作为游戏的场所。

  在创建 Place 的时候规定:每个 Place 只能有一个 Section,即 Stage(参见该系列的 第一篇 文章), 该 stage 只能容纳两名用户, 对于登录到游戏桌的用户,游戏会把他们放置到 Stage 中,如果 stage 已满,则不接受其他用户进入。

  FGServer 对每个 Place 都添加一个 Activity, 用户发送给 FGServer 的消息都通过该 Activity 的监听器来接收。

  检测用户事件

  进入/离开游戏桌:通过 Stage 的监听器来检测。

  用户发送的消息(猜拳):通过 Activity 的监听器来检测,我们把玩家发送的消息称为命令(Command), FGServer 会使用 CmdFactory 来解析这些命令。

  维持游戏桌状态

  猜拳游戏用一个列表来记录进入到游戏桌的所有用户:

  每当有用户进入游戏桌时,猜拳游戏会检查游戏桌的状态:如果游戏桌没有坐满,当前玩家需要等待,否则游戏开始。

  当用户离开游戏桌时,游戏桌中的现有玩家就需要等待。

  判断游戏胜负

  当两个玩家都出过拳以后,猜拳游戏会进行判断,给出胜负关系,发送给游戏桌中的玩家,然后重启下一轮游戏。为了方便扩展,猜拳游戏提取出了“规则”(Rule)的概念,根据当前的玩家的输入,进行计算和判断。

  FGClient

  猜拳游戏的客户端相对简单,除了提供一个简单的游戏界面以外,主要的操作是进入 Place,与 FGServer 进行消息交互。

  发送消息

  登录到 Place 以后,FGClient 能够获得 Place 中的 Activity。所有发向服务器端的消息都通过 Activity 来进行。

  接收消息

  进入 Place 以后,FGClient 可以获得当前用户在 Place 中的一个对象引用,称为 MySelfInPlace, 通过向该对象添加消息监听器,则可以获取所有发给自己的消息。其中以”@”开始的消息称为命令,当前只有两种命令: (1)@game start, (2) @game end FGClient 需要解析、执行这些命令来,最终的结果会反应的用户界面。对于普通的消息,FGClient 只是简单的显示。

  二、登录到猜拳游戏和服务器端初始化

  FGClient

  游戏启动以后首先要做的是登录到猜拳游戏,实际上是登录到 Sametime Server,所使用的服务是 Sametime Client Toolkit 中的 CommunityService, 具体的使用方法请参考该系列的 第一篇 文章。

  FGServer

  步骤一:创建 Session 对象

  略(参见该系列的 第一篇 文章)

  步骤二:登录到 Sametime 社区

  与 FGClient 所不同的是,FGServer 并不是 Sametime Server 的一个用户,所以登录的方式有所不同,需要使用 ServerAppService,该服务可以把 FGServer 这个新应用程序注册到 sametime 社区中,代码如下:

  代码 1:登录 sametime 社区

  //首先获取一个ServerAppServer 对象

  ServerAppService saService = (ServerAppService) session

  .getCompApi(ServerAppService.COMP_NAME);

  //声明FGServer是一个Server Application

  short loginType = STUserInstance.LT_SERVER_APP;

  //它所支持的服务是Constants.FINGER_GUESSING_ACTIVITY_TYPE

  int[] supportedServices =

  { Constants.FINGER_GUESSING_ACTIVITY_TYPE };

  //不通过MUX,直接连接到sametime社区中

  Connection[] connections =

  { new SocketConnection(1516, 17000), };

  saService.setConnectivity(connections);

  //添加一个Listener,读者如果看过第一篇文章,对这种Listener的编程模型应该比较熟悉

  saService.addLoginListener(new LoginHandler());

  //注意这里的登录方式,是通过Server Application的方式登录

  saService.loginAsServerApp(hostName, loginType, "FingerGuessing",

  supportedServices);

  上面代码中 FINGER_GUESSING_ACTIVITY_TYPE 是一个自定义的活动类型编号。该编号必须是唯一的,即不能于 Sametime 内置的任何活动编号和其他用户自定义活动编号重复。

  把我们自定义的活动加入 Place 有两种办法。一种是由客户端显式的调用方法 Place.addActivity(),一种是将该活动设置为 Place 的缺省活动,这样 Place 在创建时该活动就自动被加入了。我们在下面的步骤中使用第二种方法。

  步骤三:初始化 Place

  FGServer 作为服务器应用程序登录以后,最重要的工作就是初始化 Place,这一步的工作比较负杂,有多个事件的通知和处理,需要多个 Service 进行协作来完成。整个初始化流程如下图所示:

  图4:初始化 Place

  图4:初始化 Place

  (1) 向 ActivityService 和 PlaceAdminService 添加 Listener

  代码 2:添加 Listener

  activityService.addActivityServiceListener(new ActivityServiceHandler());

  placeAdminService.addPlacesAdminListener(new PlaceAdminHandler());

  (2) 当 PlaceAdminService 准备好,可以使用时,系统发出事件通知,PlaceAdminHandler 的 serverAvailable 方法被调用

  代码 3:设置缺省的 Activity 和 Section

  public void serviceAvailable(PlacesAdminEvent event){

  //设置一个缺省的 Activity,以后每当创建一个 Place 的时候,该 Activity 就会被创建

  placeAdminService.setDefaultActivity(

  Constants.FINGER_GUESSING_PLACE_TYPE,

  Constants.FINGER_GUESSING_ACTIVITY_TYPE, null);

  //猜拳游戏中,每个游戏桌只能容纳两个用户,这里通过 PlaceAdminService 来完成设置:

  //一个 Place 只有一个 Section,每个 Section 只能允许两个用户进入。

  placeAdminService.setDefaultSections(

  Constants.FINGER_GUESSING_PLACE_TYPE,

  Constants.SECTION_AMOUNT,

  Constants.SECTION_CAPACITY);

  }

  上面代码中的FINGER_GUESSING_PLACE_TYPE是我们自定义的Place类型编号。该编号同样也必须是唯一的。

  (3) 系统发出“设置缺省 Activity 成功”的事件,PlaceAdminHandler 的 defaultActivitySet 方法被调用

  代码 4:创建 Place

  public void defaultActivitySet(PlacesAdminEvent event){

  //创建三个持久化的Place

  for (int i = 0; i < Constants.PLACE_AMOUNT; i++)

  {

  placeAdminService.createPersistentPlace(

  Constants.PLACE_NAME_PREFIX + String.valueOf(i),

  Constants.PLACE_NAME_PREFIX + String.valueOf(i),

  Constants.FINGER_GUESSING_PLACE_TYPE,

  Constants.PLACE_PASSWORD, EncLevel.ENC_LEVEL_DONT_CARE);

  }

  }

  注意我们必须在设置缺省 Activity 成功事件触发后创建自己的 Place。否则无法确保我们自己的活动被加入到新创建的 Place。

  (4) 创建 place 成功以后,系统向 ActivityService 发出一个事件,用来请求一个 activity

  代码 5:处理 Request Activity 事件

  //需要注意的是:下面的代码会执行三次,因为创建了三个 Place

  public void activityRequested(ActivityServiceEvent event){

  //获取 Activity 对象

  MyActivity myActivity = event.getMyActivity();

  //必须通过 ActivityServer 接受该 Activity

  activityService.acceptActivity(myActivity, null);

  //我们终于获得了 Place 对象的引用,

  Place p = event.getPlace();

  //创建一个FGServerTable对象来封装该place

  FGServerTable table = new FGServerTable( FGServer.this, p);

  }

  (5) 在 FGServerTable 中,添加 PlaceListener

  代码 6:添加 PlaceListener

  public FGServerTable(FGServer fg, Place place)

  {

  this.fg = fg;

  this.place = place;

  this.place.addPlaceListener(new PlaceHandler());

  }

  至此为止,游戏桌的初始化全部完成,读者可以看出,费了这么多的周折,最重要的是要获取对 place 的引用,以便进行后续的操作。

  三、进入或退出游戏桌

  猜拳游戏使用 Toolkit 中的 Place 来模拟一个游戏桌,当用户进入/退出游戏桌时,实际上是进入/退出一个特定的 Place。

  FGClient

  每当用户在界面上选中一个游戏桌,点击”Enter”按钮时,FGClient 将会创建一个 FGClientTable 对象来代表该游戏桌,然后调用该对象的 enter() 方法:

  代码7:进入游戏桌

  currentTable = new FGClientTable(client, tableName);

  currentTable.enter();

  在enter方法中有如下步骤:

  步骤一:创建并进入 Place

  代码 8:进入 Place

  currentPlace = placeService.createPlace(placeName, placeName,

  EncLevel.ENC_LEVEL_DONT_CARE,

  //指定place的类型,与server端创建时一致

  Constants.FINGER_GUESSING_PLACE_TYPE);

  currentPlace.enter(

  //该place的密码,由server端提供

  Constants.PLACE_PASSWORD,

  //进入一个现有的place(place在server端已经创建)

  PlacesConstants.PLACE_CREATION_JOIN,

  //进入到stage中

  true);

  步骤二:实现 PlaceListener

  在 enter 方法之前增加语句:

  代码 9

  place.addPlaceListener(new PlaceHandler());

  PlaceHandler 的实现如下:

  代码 10:客户端 Place Listener

  private class PlaceHandler extends PlaceAdapter

  {

  public void entered(PlaceEvent event)

  {

  Place p = event.getPlace();

  mySelfInPlace = p.getMyselfInPlace();

  // 添加一个Message Handler来接收从服务器端发送的消息

  mySelfInPlace.addMyMsgListener(new MyMsgHandler());

  //已经成功的进入Place,调用client的相关方法来改变UI,比如Enable “Leave” 按钮

  client.enterTable(getName());

  }

  public void enterFailed(PlaceEvent event)

  {

  //进入place 失败, 可能是place已经满了,通知client更新UI

  client.enterFailed(getName(), event.getReason());

  }

  public void activityAdded(PlaceEvent event)

  {

  //在此处能检测到server增加的Activity, 以后需要通过它向server发送消息

  activity = event.getActivity();

  }

  }

  步骤三:实现MyMsgListener

  代码 11:Message Listener

  private class MyMsgHandler implements MyMsgListener

  {

  public void textReceived(MyselfEvent event)

  {

  String text = event.getText();

  // 如果从server端收到的message是一个命令(以@开始的消息),则由CmdFactory进行处理

  if (CmdFactory.isCommand(text))

  {

  CmdBase cmd = CmdFactory.getInstance(text);

  cmd.processCmd(client, text);

  }

  else

  {

  // 这是一个普通消息,直接显示到界面的消息面板上

  client.appendMsg(text);

  }

  }

  }

  }

  至此为止,程序已经进入到一个游戏桌中,并且添加了适当的 Listener,已经为玩游戏做好了准备,玩家退出游戏桌比较简单,只需要调用 currentPlace.leave() 方法,然后更新界面(比如 Disable “Leave” 按钮,Enable ”Enter”按钮)即可。

  FGServer:

  我们在“服务器端初始化”一节已经提到,FGServer 在初始化时会创建 3 个 FGServerTable 来表示游戏桌,每个 FGServerTable 对象都包含一个 Place 对象(注意,这里的 Place 属于 server 端,所在的包为 com.lotus.sametime.placessa, 而不是 client 端的 com.lotus.sametime.places)。Place 对象中添加的几个重要 Listener 如下:

  步骤一:实现 PlaceListener

  代码12:服务器端 PlaceListener

  private class PlaceHandler extends PlaceAdapter

  {

  public void sectionAdded(PlaceEvent event)

  {

  Section section = event.getSection();

  if (section.isStage())

  {

  //如果新添加的section 是stage, 则添加一个listener, 实际上由于在创建Place时

  //的设置,一个Place只可能有一个缺省的section: stage

  stage = section;

  stage.addSectionListener(new SectionHandler());

  }

  }

  public void activityAdded(PlaceEvent event)

  {

  activity = event.getActivity();

  //对Activity 添加Message Listener, 用来接收从客户端发送的消息

  activity.addIncomingMessageListener(new IncomingMessageHandler());

  }

  }

  步骤二:实现 SectionListener

  Section Listener 主要的功能是检测用户进入/离开 Section 的事件,从而维持游戏桌的状态:

  代码 13:检测用户进入/离开 Section 的事件

  private class SectionHandler extends SectionAdapter

  {

  //有新玩家进入到section中

  public void usersEntered(SectionEvent event)

  {

  UserInPlace[] theUsers = event.getEnteredUsers();

  UserInPlace user = event.getEnteredUsers()[0];

  //向已经在游戏桌中等待的其他玩家发送消息

  broadcast("User " + user.getName() + " entered table " + getName());

  // 把新玩家加入到列表中

  addToPlayerList(user);

  if (isFull())

  {

  // 如果游戏桌已经满了, 发送命令@game start

  isGameStarted = true;

  broadcast(Constants.CMD_GAMESTART);

  broadcast("Game started - " + getPlayerNames());

  }

  else

  {

  broadcast("Waiting for other players in " + getName());

  }

  }

  // 玩家离开的游戏桌

  public void userLeft(SectionEvent event)

  {

  UserInPlace user = event.getDepartedUser();

  // 从游戏列表中把玩家删除

  removeFromPlayerList(user);

  isGameStarted = false;

  broadcast("User " + user.getName() + " left from table "

  + getName());

  // 此时,游戏桌未满, 发送命令@game end

  isGameStarted = false;

  broadcast(Constants.CMD_GAMEEND);

  // 告诉游戏桌中的现有玩家,需要等待

  broadcast("Waiting for other players in " + getName());

  }

  }

  步骤三:为 Activity 实现 IncomingMessage Listener

  代码 14:处理从 server 端收到的命令

  private class IncomingMessageHandler extends IncomingMessageAdapter

  {

  public void textReceived(MessageEvent event)

  {

  String text = event.getText();

  PlaceMember pm = event.getSender();

  // 安全起见,先查找该用户是否在游戏桌中

  FGServerUser user = find(pm);

  if (null == user)

  {

  Log.error("Can't find user " + pm);

  return;

  }

  // 执行FGClient 发出的命令

  CmdBase cmd = CmdFactory.getInstance(text);

  cmd.processCmd(fg, user, text);

  }

  }

  四、在游戏桌上同另一个玩家进行游戏

  当两个玩家进入到同一个游戏桌后,FGServerTable 能通过 SectionListener 检测到游戏桌已满,这时候就会给两个玩家发送游戏开始的命令: @game start。FGClientTable 通过 MyMsgListener 收到以后,则会 Enable 游戏界面上的三个猜拳按钮:“Stone”,“Scissor”,“Paper”,玩家就可以出拳进行游戏了。图 5 展示了猜拳游戏的一个典型场景:

  该图包含两个已经进入到游戏桌的用户:user1(位于 FGClient1 中),user2(位于 FGClient2 中),图中还展示了一个服务器 FGServer 用于处理客户端的请求。

  图 5:FGClient 和 FGServer 交互图

  图 5:FGClient 和 FGServer 交互图

  步骤一:位于 FGClient 1 的玩家发出猜拳命令: guess stone

  在该场景中,user1 首先发出猜拳命令,下面的代码会被调用(位于 FGClientTable 中):

  代码 15:用户发出猜拳命令

  public void guess(String input)

  {

  //使猜拳按钮不可再次点击

  client.setGuessEnable(false);

  //通过Activity向服务器发送消息,根据点击按钮的不同,参数input的值可能是:

  // (1) guess stone, (2) guess scissor (3)guess paper

  activity.sendText(input);

  }

  步骤二:FGServer 判断当前状态

  FGServer 接收到客户端发送的命令以后,会进行一系列处理,最终 FGServerTable 的 checkStatus 方法会被调用。

  代码 16:检查当前状态

  public void checkStatus(FGServerUser currentPlayer)

  { if (isWaitingForJudge())

  {

  // 如果两个玩家都已经发出猜拳命令,则游戏判断胜负

  RuleBase rule = RuleFactory.getInstance(Constants.RULE_NAME);

  if (rule.judge(this, players))

  {

  // 向两个玩家发送消息

  this.sendGameResult(rule);

  //清除当前的猜拳结果,本轮游戏结束

  this.clearGuessing();

  // 发送命令,下一轮游戏开始

  broadcast(Constants.CMD_GAMESTART);

  }

  }

  else

  {

  // 只有当前玩家发出猜拳命令,分别向两个用户发送消息, 参见上图的步骤2

  // (黄色箭头)

  currentPlayer.sendText("Waiting for other player to guess...");

  sendTextExceptUser(currentPlayer, currentPlayer.getName()

  + " guessed.");

  }

  }

  步骤三. 位于 FGClient2 的玩家发出猜拳命令: guess paper

  与步骤一相同,参见 代码 15

  步骤四. FGServer 再次判断当前状态

  此时两个玩家都已经猜拳,FGServer将判断胜负关系,发送消息给玩家(参见 图5 的绿色箭头)

  调用的代码与步骤二相同,参见 代码16。

  总结

  本文利用了 Server Toolkit 提供的 ServerAppService、PlacesAdminService 和 ActivityService 扩展了 Sametime Server 的功能,完成了一个简单的猜拳游戏。用户可以通过本文体验到 Server Toolkit 的开发方式和技巧,从而在此基础上进一步深入,利用这些 API 定制自己的应用,完成特定的需求。

相关搜索:
关注此文读者还看过
文章排行
本周
本月
最近更新
关于我们|About us|网站律师|天极服务|电子杂志|RSS订阅|加入我们|网站地图
TMG
Copyright (C) 1999-2009 Chinabyte.com, All Rights Reserved 版权所有 天极网络
商务联系、网站内容、合作建议:010-82657868
版权声明 在线提交意见反馈 渝ICP证B2-20030003号
经营性网站备案信息 网警备案 中国网站排名
天极传媒:天极网|比特网|IT专家网|IT商网|52PK游戏网|IT分众