RedDwarf-Javaã§ãªã³ã©ã€ã³ã²ãŒã ãéçºããããã®ãµãŒããŒãã©ãããã©ãŒã ã®èšäºã§
ãã²ãŒã ãµãŒããŒãäœæããããã®ãã®ãã©ãããã©ãŒã ã®æ©èœã«ã€ããŠèª¬æããŸããã ãã®èšäºã§ã¯ãRedDwarfã䜿çšããŠãµãŒããŒãäœæããæ¹æ³ãäŸã«ç€ºããŸãã
äŸãšããŠãã²ãŒã ãRock-Paper-Scissorsãã®ãªã³ã©ã€ã³å®è£
ãäœæããããšã決å®ãããŸããã
ãã®èšäºã§ã¯ããµãŒããŒãäœæããŠèµ·åããããšããŸãã
次ã®èšäºã§ã¯ããã®ãµãŒããŒçšã®å°ããªã¯ã©ã€ã¢ã³ããäœæãããã®ããã©ãŒãã³ã¹ã確èªããŸãã
ä»äºã®æºå
ãŸã
ããããã sgs-server-dist-0.10.2.zipã¢ãŒã«ã€ãã«ããReddwarfãµãŒããŒãããŠã³ããŒãããsgs-server-dist-0.10.2ãã©ã«ããŒã«ã³ã³ãã³ãã解åããå¿
èŠããããŸãã
ãããžã§ã¯ãäœæ
ãæ°ã«å
¥ãã®éçºç°å¢ã§ãããžã§ã¯ããäœæããŸãã
ãããžã§ã¯ãã¯ã·ã³ãã«ã«ãªããããMavenã¯äœ¿çšããŸããã
éçºã«ã¯ãsgs-server-dist-0.10.2 \ lib \ãã£ã¬ã¯ããªã«ããsgs-server-api-0.10.2.jarã©ã€ãã©ãªãå¿
èŠã§ã
META-INFãã©ã«ããŒãäœæããŸããããã«ã¯ããããã§ã¹ããã¡ã€ã«MANIFEST.MFãå«ãŸããŠããå¿
èŠããããŸãã ããããªããšããã©ãããã©ãŒã ã¯ãããžã§ã¯ãjarãã¡ã€ã«ã§ã®äœæ¥ãæåŠããŸãã ç§ã®ãã¡ã€ã«ã«ã¯1è¡ããå«ãŸããŠããŸããïŒ
ãããã§ã¹ãããŒãžã§ã³ïŒ1.0
ãŸããMETA-INFãã©ã«ããŒã«app.propertiesãã¡ã€ã«ãäœæããå¿
èŠããããŸãã ãã®ãã¡ã€ã«ã«ã¯ããµãŒããŒã®èµ·åèšå®ãå«ãŸããŠããŸãã ãããžã§ã¯ãã®å Žåããã¡ã€ã«ã«ã¯æ¬¡ã®ããããã£ãå«ãŸããŠããŸãã
ããã¯ãæäœéå¿
èŠãªãªãã·ã§ã³ã®ã»ããã§ãã éçºäžã«ã次ã®ããããã£ãåŒãç¶ãæçšãªå ŽåããããŸãã
- com.sun.sgs.impl.transport.tcp.listen.port-ãµãŒããŒããªãã¹ã³ããããŒãïŒããã©ã«ãã§ã¯62964ïŒ
- com.sun.sgs.app.authenticators-èªèšŒãæ
åœããã¯ã©ã¹ã®ååïŒèªèšŒããã»ã¹ã¯ã²ãŒã ããžãã¯ããåé€ãããç¬ç«ããã¢ãžã¥ãŒã«ãšããŠäœ¿çšã§ããŸãïŒ
- com.sun.sgs.impl.service.session.allow.new.login-å¥ã®ã¯ã©ã€ã¢ã³ãããæ¥ç¶ããããã¬ãŒã€ãŒãæ¥ç¶ã§ããããã«ãããã©ããã trueã®å Žåãã²ãŒã å
ã«ãã人ãã¹ããŒããŸãã falseã®å Žåãå¥ã®ã¯ã©ã€ã¢ã³ãããã®æ¥ç¶ãèš±å¯ããŸããã
ãã®ä»ã®ããããã£ã®è©³çŽ°ã«ã€ããŠã¯ã
ããã¥ã¡ã³ããã芧ãã ããã
ã²ãŒã ã¢ãŒããã¯ãã£
ã²ãŒã ã«ã¯æ¬¡ã®ãšã³ãã£ãã£ãå¿
èŠã§ãã
ãµãŒã㌠-ãã¬ã€ã€ãŒã®ãªã¹ãããªã³ã©ã€ã³ã§ä¿åããæ¥ç¶ã®åŠçãåŠçããã¯ã©ã¹ã
ãã¬ãŒã€ãŒ -
ãã¬ãŒã€ãŒãè¡šããŸãã ãã¬ã€ã€ãŒã«ã¯æ¬¡ã®å±æ§ããããŸãïŒååïŒåããã°ã€ã³ïŒãšãã€ã³ãæ°ã æŠéã«åå ã§ããŸãã
ããã« -ããã«ã§ãã ãã®ãªããžã§ã¯ãã§ã¯ããã¬ãŒã€ãŒã®å¿çãåŸ
ã£ãŠåè
ã決å®ããŸãã 2人ã®ãã¬ãŒã€ãŒãžã®ãªã³ã¯ãå«ãŸããŠããŸãã
æŠåšã¯ãçŽæ¥ç³ãã¯ãã¿ãçŽãªã©ã®æŠåšã®åçŽãªåæã§ãã
ã¯ã©ã¹å³ã®åœ¢åŒã§æãããŠããå Žåã次ã®ããšãããããŸãã

ãã¹ãŠã®ã²ãŒã ãšã³ãã£ãã£ïŒæŠåšãé€ãïŒã¯ããµãŒããŒã®å®è¡äžã«ãã©ã³ã¶ã¯ã·ã§ã³æ§ãæäŸããå
éšããŒã¿ããŒã¹ã«æ ŒçŽãããçžäºã«åç
§ãããããjava.io.Serializableããã³com.sun.sgs.app.ManagedObjectã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããå¿
èŠããããŸãã
ãµãŒããŒã¯ã©ã¹ã ãã¬ãŒã€ãŒã®åæåãšæ¥ç¶
Serverã¯ã©ã¹ã¯ãµãŒããŒã®èµ·åãã€ã³ãã§ãããããcom.sun.sgs.app.AppListenerã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããå¿
èŠããããŸãã
void initialize(Properties props)
ã¯ããµãŒããŒã®æåã®èµ·åæã«åŒã³åºãããŸãã äœæ¥ã«å¿
èŠãªåæå€ã§å
éšããŒã¿ããŒã¹ãæºãããŸãã éèŠãªæ©èœïŒãµãŒããŒãåæ¢ïŒãŸãã¯åŒ·å¶çµäºïŒããŠããåèµ·åããå Žåããã®ã¡ãœãã
ã¯åŒã³åºãã
ãŸããã å
éšããŒã¿ããŒã¹ã¯ãµãŒããŒãèµ·åãããŸã§ä¿åãããåæ¢ããç¬éããäœæ¥ãç¶ããããšãã§ããŸãã
ClientSessionListener loggedIn(ClientSession session)
ã¯ãèªèšŒãæåããåŸã«åŒã³åºããããã¬ãŒã€ãŒãè¡šããªããžã§ã¯ããè¿ãå¿
èŠããããŸãã ãã®äŸã§ã¯ãããã¯Playerã«ãªããŸãã
ãµãŒããŒã«æ¥ç¶ãããŠãããã¹ãŠã®ãã¬ãŒã€ãŒã¯ãç¹å¥ãªã³ã¬ã¯ã·ã§ã³ã«ä¿åãããŸãã Reddwarfã«ã¯ãã²ãŒã ãšã³ãã£ãã£çšã®ScalableHashMapã®ç¹å¥ãªã³ã¬ã¯ã·ã§ã³ããããŸãã ãã®ã³ã¬ã¯ã·ã§ã³ã®å©ç¹ã¯ãå€æŽããããšãå®å
šã«ã§ã¯ãªãéšåçã«ãããã¯ãããããšã§ãïŒå
éšããŒã¿ããŒã¹ã®ããã¯ãæå³ããŸãïŒã ãŸããServerãªããžã§ã¯ãã§ã¯ãã³ã¬ã¯ã·ã§ã³èªäœã§ã¯ãªããã³ã¬ã¯ã·ã§ã³ãžã®ãªã³ã¯ïŒManagedReferenceïŒãä¿åããŸãã
èšèããè¡çºã«ç§»ããšã次ã®ã³ãŒããåŸãããŸãã
package hello.reddwarf.server; import java.io.Serializable; import com.sun.sgs.app.*; import com.sun.sgs.app.util.ScalableHashMap; import java.util.Properties; public class Server implements AppListener, Serializable, ManagedObject { public ManagedReference<ScalableHashMap<String, Player>> onlinePlayersRef; @Override public void initialize(Properties props) {
ããŒã¿ããŒã¹ãæäœããã«ã¯ãDataManagerã䜿çšããŸããããã«ãããããŒã¿ããŒã¹ãžã®æžã蟌ã¿ãããŒã¿ããŒã¹ããã®èªã¿åããManagedReferenceãªã³ã¯ã®äœæãå¯èœã«ãªããŸãã ããŒã¿ããŒã¹ã¯ããŒãšå€ã®ã¹ãã¬ãŒãžã§ããããããplayerããšãããã¬ãã£ãã¯ã¹ã®ä»ãããã¬ãŒã€ãŒã®ååãããŒãšããŠäœ¿çšãããPlayerãªããžã§ã¯ãå
šäœãå€ã«ã·ãªã¢ã«åãããŸãã ããŒã¹ãããã¬ãŒã€ãŒãããŒãããé¢æ°ãäœæããŸãïŒãã¬ãŒã€ãŒãããŒã¿ããŒã¹ã«èŠã€ãããªãå Žåã¯äœæããŸãïŒã
private Player loadOrRegister(String name) { try { return (Player) AppContext.getDataManager().getBindingForUpdate("player." + name); } catch (NameNotBoundException e) {
ãã¬ãŒã€ãŒã®ã¯ã©ã¹ãšãããã³ã«
次ã¯Playerã¯ã©ã¹ãäœæããçªã§ãã ãã®ã¯ã©ã¹ã¯ãã¬ãŒã€ãŒãè¡šãããã©ãããã©ãŒã ããçä¿¡ã¡ãã»ãŒãžã®éç¥ãåãåããŸãã ããã§ã¯ããããã³ã«ã«ã€ããŠè©±ããŸãããã Reddwarfã䜿çšãããšãçä¿¡ããã³çºä¿¡ã¡ãã»ãŒãžããã€ãã®é
åãšããŠåŠçã§ãããããã³ã«ã®å®è£
ã¯ã²ãŒã éçºè
ã®è£éã«ä»»ãããŸãã ã²ãŒã ãããããããã§ã¯ãåçŽãªããã¹ããããã³ã«ã䜿çšããŸãã
ïŒ
server- > clientïŒ
SCORE <number> -ãµãŒããŒã¯ãã¬ã€ã€ãŒã«ãã€ã³ãæ°ãäŒããŸã
ïŒã¯ã©ã€ã¢ã³ã->ãµãŒããŒïŒ
PLAY-ã²ãŒã ãéå§ããããã®ãã¬ãŒã€ãŒã®ãªã¯ãšã¹ã
ïŒãµãŒããŒ->ã¯ã©ã€ã¢ã³ãïŒ
BATLE <åå> -æå®ããããã¬ã€ã€ãŒãšã®æŠããå§ãŸããŸãã
ïŒãµãŒããŒ->ã¯ã©ã€ã¢ã³ãïŒ
ãšã©ãŒ -æŠéã®ãã¬ã€ã€ãŒãèŠã€ãããŸããã§ããïŒãµãŒããŒã«èª°ãããªããããã¹ãŠã®æŠéã«åå ããŠããŸããïŒ
ïŒã¯ã©ã€ã¢ã³ã->ãµãŒããŒïŒ
ROCK-ãã¬ã€ã€ãŒã¯ãStoneããšèšããŸã
ïŒã¯ã©ã€ã¢ã³ã->ãµãŒããŒïŒ
SCISSORS-ãã¬ã€ã€ãŒã¯ãã¯ãã¿ããšèšããŸã
ïŒã¯ã©ã€ã¢ã³ã->ãµãŒããŒïŒ
çŽ -ãã¬ã€ã€ãŒã¯ãçŽããšèšããŸã
ïŒãµãŒããŒ->ã¯ã©ã€ã¢ã³ãïŒ
DRAW-æç»
ïŒãµãŒããŒ->ã¯ã©ã€ã¢ã³ãïŒ
WON-ãã¬ãŒã€ãŒãåã¡ãŸãã
ïŒãµãŒããŒ->ã¯ã©ã€ã¢ã³ãïŒ
LOST-ãã¬ã€ã€ãŒã倱ãããŸãã
ãããã³ã«ããããã¬ãŒã€ãŒã®ã¢ã¯ã·ã§ã³ãšæ©èœã®ã·ãŒã±ã³ã¹ãç解ã§ãããããããã«ã€ããŠåå¥ã«èª¬æããããšã¯ããŸããã
ãã®ã³ãŒãã䜿çšããŠãããã¹ãããã€ãã«ãšã³ã³ãŒããããããã®éãè¡ãããšãã§ããŸãã
package hello.reddwarf.server; import java.nio.ByteBuffer; public class Messages { public static ByteBuffer encodeString(String s) { return ByteBuffer.wrap(s.getBytes()); } public static String decodeString(ByteBuffer message) { byte[] bytes = new byte[message.remaining()]; message.get(bytes); return new String(bytes); } }
次ã«ããã¬ãŒã€ãŒã®ãªããžã§ã¯ãã®äœæã«é²ã¿ãŸãã
ãã¬ãŒã€ãŒã¯æ¬¡ã®ãã£ãŒã«ããä¿æããŸãã
- å
- ç¹æ°
- ãµãŒããŒãªã³ã¯ïŒãªã³ã©ã€ã³ãã¬ãŒã€ãŒã®ãªã¹ãã«ã¢ã¯ã»ã¹ããããïŒ
- ã»ãã·ã§ã³ãžã®ãªã³ã¯ïŒã¯ã©ã€ã¢ã³ãã«ã¡ãã»ãŒãžãéä¿¡ããããïŒ
- æŠéãžã®ãªã³ã¯ïŒãã¬ã€ã€ãŒãæŠéäžã®å Žåãããã§ãªãå Žåã¯nullïŒ
package hello.reddwarf.server; import com.sun.sgs.app.*; import com.sun.sgs.app.util.ScalableHashMap; import java.io.Serializable; import java.nio.ByteBuffer; import java.util.*; public class Player implements Serializable, ManagedObject, ClientSessionListener { private final static Random random = new Random(); public final String name; private int score;
æŠåšããã³æŠéã¯ã©ã¹
æŠåšã®åæã¯éåžžã«åçŽã§ãããã³ã¡ã³ãã¯äžèŠã§ãã
package hello.reddwarf.server; public enum Weapon { ROCK, PAPER, SCISSORS; boolean beats(Weapon other) { return other != null && this != other && this.ordinal() == (other.ordinal() + 1) % values().length; } }
æŠãã«ç§»ããŸãã
æŠéã«ã¯äžæã®èå¥åãããã2人ã®ãã¬ã€ã€ãŒãžã®ãªã³ã¯ããã®åçãããã³ã¢ã¯ãã£ããã£ãã©ã°ãå«ãŸããŠããŸãã
æŠéãäœæããããšãå¥ã®ã¿ã¹ã¯ãèµ·åããã5ç§ã§æŠéãå®äºããŸãã
ãã®æéãçµéãããšãæŠéã®çµæãåèšãããŸãã ãã¬ã€ã€ãŒã®1人ã ããçããåºããå Žåãäž¡æ¹ã®å Žåãåè
ãšèŠãªãããŸã-åè
ã¯éåžžã®èŠåãããããããã«åŸã£ãŠæ±ºå®ãããŸãã
ã¿ã¹ã¯ã¯ãAppContext.getTaskManagerïŒïŒã䜿çšããŠååŸã§ããTaskManagerãµãŒãã¹ã䜿çšããŠå®è¡ãããŸãã ãã®ãããŒãžã£ãŒã䜿çšãããšãåå¥ã®ãã©ã³ã¶ã¯ã·ã§ã³ã§å®è¡ãããã¿ã¹ã¯ãããã«å®è¡ããããæå®ããæéã®åŸã«å®è¡ããããå®æçã«å®è¡ã§ããŸãã äºæ³ã©ããããã¹ãŠã®ã¿ã¹ã¯ã¯å
éšããŒã¿ããŒã¹ã«ãä¿åãããŸããã€ãŸãããµãŒããŒã®åèµ·ååŸã«å®è¡ãããŸãã
ãããã£ãŠãã¯ã©ã¹ã³ãŒãã¯Battleã§ãã
package hello.reddwarf.server; import com.sun.sgs.app.AppContext; import com.sun.sgs.app.ManagedObject; import com.sun.sgs.app.ManagedReference; import com.sun.sgs.app.Task; import java.io.Serializable; import java.util.concurrent.atomic.AtomicInteger; public class Battle implements ManagedObject, Serializable { // 5 private static final long BATTLE_TIME_MS = 5000; enum Result { DRAW, WON, LOST } private boolean active; private ManagedReference<Player> starterPlayerRef; private ManagedReference<Player> invitedPlayerRef; private Weapon starterWeapon = null; private Weapon invitedWeapon = null; public Battle(Player starterPlayer, Player invitedPlayer) { starterPlayerRef = AppContext.getDataManager().createReference(starterPlayer); invitedPlayerRef = AppContext.getDataManager().createReference(invitedPlayer); active = false; } public void start(){ active = true; AppContext.getTaskManager().scheduleTask(new BattleTimeout(this), BATTLE_TIME_MS); } public void answer(Player player, Weapon weapon){ if (active) { if (player.name.equals(starterPlayerRef.get().name)) { starterWeapon = weapon; } else { invitedWeapon = weapon; } } } private void finish() { active = false; Player starterPlayer = starterPlayerRef.getForUpdate(); Player invitedPlayer = invitedPlayerRef.getForUpdate(); if (starterWeapon != null && starterWeapon.beats(invitedWeapon)) { starterPlayer.battleResult(Result.WON); invitedPlayer.battleResult(Result.LOST); } else if (invitedWeapon != null && invitedWeapon.beats(starterWeapon)) { invitedPlayer.battleResult(Result.WON); starterPlayer.battleResult(Result.LOST); } else { starterPlayer.battleResult(Result.DRAW); invitedPlayer.battleResult(Result.DRAW); } AppContext.getDataManager().removeObject(this); } private static class BattleTimeout implements Serializable, Task { private ManagedReference<Battle> battleRef; public BattleTimeout(Battle battle) { battleRef = AppContext.getDataManager().createReference(battle); } @Override public void run() throws Exception { battleRef.getForUpdate().finish(); } } }
ãã®ã³ãŒããèªããšããå
éšBattleTimeoutã¯ã©ã¹ãéçã«ãªããããã«ãžã®ãªã³ã¯ãæ瀺çã«ä¿åããã®ã¯ãªãã§ããïŒ ééçãšããŠå®£èšããããã«ãã£ãŒã«ãã«çŽæ¥ã¢ã¯ã»ã¹ã§ããŸããã
å®éãééçå
éšã¯ã©ã¹ã¯èŠªããã«ãžã®ãªã³ã¯ãæé»çãªåœ¢åŒã§ä¿åãããããä»ããŠããã«ã«ã¢ã¯ã»ã¹ããŸãã ãã ããReddwarfãã©ãããã©ãŒã ïŒãã©ã³ã¶ã¯ã·ã§ã³ïŒã®æ©èœã¯ãå¥ã®ãã©ã³ã¶ã¯ã·ã§ã³ããManagedObjectïŒBattleïŒã«çŽæ¥ã¢ã¯ã»ã¹ããããšãçŠæ¢ããŠããŸãããã®å ŽåãäŸå€ãã¹ããŒãããŸãã å¥ã®ãã©ã³ã¶ã¯ã·ã§ã³å
ã®ãªããžã§ã¯ããžã®çŽæ¥åç
§ã¯æ£ãããããŸããã éçãªå
éšã¯ã©ã¹ã®ã¿ã䜿çšãããšãããã©ãããã©ãŒã äœæè
ã®æšå¥šäºé
ã¯ãããã«é¢é£ããŠããŸãã
ãŸããåç
§ã«ãã管ç察象ãªããžã§ã¯ãã®åä¿¡ã«æ³šæããããšæããŸãã
ManagedReferenceã®äžèšã®ã³ãŒãã¯ãgetïŒïŒã¡ãœãããšgetForUpdateïŒïŒã®äž¡æ¹ã䜿çšããŸãã
ååãšããŠãgetïŒïŒã®ã¿ã䜿çšã§ããŸãã getForUpdateïŒïŒã䜿çšãããšããµãŒããŒã¯ããã©ã³ã¶ã¯ã·ã§ã³ãå®äºããåã«ã©ã®ãªããžã§ã¯ããå€æŽãããããç¥ãã競åãããã©ã³ã¶ã¯ã·ã§ã³ãæ€åºãããå Žåãå°ãåã«ã¿ã¹ã¯ããã£ã³ã»ã«ã§ããŸãã ããã«ãããgetïŒïŒã䜿çšããå Žåã«æ¯ã¹ãŠé床ãããããåäžããŸãã
æåŸã«ããµãŒããŒã®æºåãã»ãŒæŽããŸããã
ãã®ã³ã°ãå°ãè¿œå ãïŒç°¡åã«ããããã«java.util.loggingã䜿çšããŸãïŒããããžã§ã¯ãããã«ãã§ããŸãã
ã¢ã»ã³ããªã®çµæãšããŠãjarãã¡ã€ã«ãããšãã°deploy.jarãååŸããå¿
èŠããããŸãã
ããããã¹ãŠãæåã§åéããããªãå Žåã¯ãå®æããdeploy.jarãã¡ã€ã«
ãããããååŸã§ã
ãŸã ã
ãã®ãã¡ã€ã«ã¯sgs-server-dist-0.10.2 \ distã«é
眮ããå¿
èŠããããŸãã
sgs-server-dist-0.10.2ãã£ã¬ã¯ããªã«ç§»åãããã次ã®ã³ãã³ããå®è¡ããŸãã
java -jar bin/sgs-boot.jar
ãã®çµæãã³ã³ãœãŒã«ã«æ¬¡ã®ããã«è¡šç€ºãããŸãã
02, 2012 9:45:19 PM com.sun.sgs.impl.kernel.Kernel <init> INFO: The Kernel is ready, version: 0.10.2.1 02, 2012 9:45:19 PM com.sun.sgs.impl.service.data.store.DataStoreImpl <init> INFO: Creating database directory : C:\sgs-server-dist-0.10.2.1\data\dsdb 02, 2012 9:45:19 PM com.sun.sgs.impl.service.watchdog.WatchdogServerImpl registerNode INFO: node:com.sun.sgs.impl.service.watchdog.NodeImpl[1,health:GREEN,backup:(none)]@black registered 02, 2012 9:45:19 PM hello.reddwarf.server.Server initialize INFO: Starting new Rock-Paper-Scissors Server. Initialized database. 02, 2012 9:45:19 PM com.sun.sgs.impl.kernel.Kernel startApplication INFO: RockPaperScissors: application is ready
ãã£ãïŒ ãµãŒããŒãèµ·åããŸããïŒ ããã§ãã¯ã©ã€ã¢ã³ãã«å¯ŸåŠã§ããŸãã
Rock-Paper-Paperãªã³ã©ã€ã³ã²ãŒã ã®äŸã䜿çšããReddwarfïŒClientåç
§è³æ
ãµãŒããŒAPI Javadocã³ãã¥ããã£ããã¥ã¡ã³ããããžã§ã¯ããã©ãŒã©ã