ÇáËÉʵÏÖ¿ÉÉìËõÐÔ£¬ÈÝ´íÐÔ£¬ºÍ¸º
ÔØÆ½ºâµÄ´ó¹æÄ£¶àÈËÔÚÏßϵͳ


By: 
Éñ×ÚÚ¤ºÆ

¼ò½é£º

±¾ÎÄÒÔÎÒµÄOpenPokerÏîĿΪÀý½éÉÜÁíÒ»ÖÖ¹¹½¨´ó¹æÄ£¶àÈËÔÚÏßϵͳµÄ·½°¸¡£OpenPokerÊÇÒ»¸ö´óÐͶàÈËÆË¿ËÍøÓΣ¬ÄÚ½¨Ö§³ÖÁËÈÝ´íÄÜÁ¦£¬¸ºÔØÆ½ºâºÍÎÞÏÞÖÆµÄ¹æÄ£´óС¡£OpenPokerµÄÔ´´úÂë×ñÑ­GPLЭÒé¿ÉÒÔ´ÓÎÒµÄÍøÕ¾ÏÂÔØ£¬´óÔ¼°üº¬Ò»ÍòÐдúÂ룬ÓÐÈý·ÖÖ®Ò»ÊÇÓÃÀ´²âÊԵġ£

ÔÚOpenpoker×îÖÕ°æ³ǫ֮̈ǰ£¬ÎÒ»¨Á˺ܴó¾«Á¦Éè¼Æ²Î¿¼£¬³¢ÊÔ¹ýDelphi, Python, C#£¬C/C++»¹ÓÐScheme¡£ÎÒÉõÖÁ»¹ÓÃCommon LispÍê³ÉÁËÒ»¸ö¿ÉÔËÐеÄPokerÒýÇæ¡£ËäÈ»ÎÒ»¨ÁË9¸ö¶àÔÂÑо¿Éè¼Æ£¬×îÖÕ´úÂë±àдȴֻÓÃÁË6¸öÐÇÆÚ£¬Õâ×îºóµÄ¸ßЧÂÊÒª¹é¹¦ÓÚÑ¡ÔñÁËErlang×÷Ϊ±àдƽ̨¡£

¸ù¾Ý±È½Ï£¬Àϰ汾µÄOpenPokerÐèÒª4¡«5¸öÈ˵ÄС×é9¸öÔÂʱ¼äÍê³É¡£Ô­°àÈËÂí»¹ÁíÍâÍê³ÉÁËÒ»¸öWindows°æµÄ¿Í»§¶Ë£¬¾ÍËã°ÑÕâ¸ö¿ª·¢Ê±¼äµÄÒ»°ë£¨1¸ö°ëÔ£©Ëã½øÈ¥£¬Ò²±ÈÔ¤ÆÚµÄ18¸öÔÂÉٵö࣬¾Íµ±½ñÓÎÏ·¿ª·¢µÄ¿Í¹Û»·¾³£¬Èç´Ë¿É¹ÛµÄʱ¼ä½ÚÊ¡²»¿ÉС¿´£¡


ʲôÊÇErlang

ÎÒ½¨ÒéÄãÏȶÁÒ»ÏÂErlang FAQ£¬²»¹ýÎÒÔÚÕâÀᄀÁ¿¸ÅÀ¨Ò»Ï£º

ErlangÊÇÒ»¸ö½á¹¹»¯£¬¶¯Ì¬ÀàÐͱà³ÌÓïÑÔ£¬ÄÚ½¨²¢ÐмÆËãÖ§³Ö¡£×î³õÊÇÓɰ®Á¢ÐÅרÃÅΪͨÐÅÓ¦ÓÃÉè¼ÆµÄ£¬±ÈÈç¿ØÖÆ½»»»»ú»òÕ߱任ЭÒéµÈ£¬Òò´Ë·Ç³£ÊʺÏÓÚ¹¹½¨·Ö²¼Ê½£¬ÊµÊ±Èí²¢ÐмÆËãϵͳ¡£

ʹÓÃErlang±àд³öµÄÓ¦ÓÃÔËÐÐʱͨ³£ÓɳÉǧÉÏÍò¸öÇáÁ¿¼¶½ø³Ì×é³É£¬²¢Í¨¹ýÏûÏ¢´«µÝÏ໥ͨѶ¡£½ø³Ì¼äÉÏÏÂÎÄÇл»¶ÔÓÚErlangÀ´Ëµ½ö½öÖ»ÊÇÒ»Á½¸ö»·½Ú£¬±ÈÆðC³ÌÐòµÄÏß³ÌÇл»Òª¸ßЧµÃ¶àµÃ¶àÁË¡£

ʹÓÃErlangÀ´±àд·Ö²¼Ê½Ó¦ÓÃÒª¼òµ¥µÄ¶à£¬ÒòΪËüµÄ·Ö²¼Ê½»úÖÆÊÇ͸Ã÷µÄ£º¶ÔÓÚ³ÌÐòÀ´Ëµ²¢²»ÖªµÀ×Ô¼ºÊÇÔÚ·Ö²¼Ê½ÔËÐС£

ErlangÔËÐÐʱ»·¾³ÊÇÒ»¸öÐéÄâ»ú£¬ÓеãÏñJavaÐéÄâ»ú£¬ÕâÑù´úÂëÒ»¾­±àÒ룬ͬÑù¿ÉÒÔËæ´¦ÔËÐС£ËüµÄÔËÐÐʱϵͳÉõÖÁÔÊÐí´úÂëÔÚ²»±»ÖжϵÄÇé¿öϸüС£ÁíÍâÈç¹ûÄãÐèÒª¸ü¸ßЧµÄ»°£¬×Ö½Ú´úÂëÒ²¿ÉÒÔ±àÒë³É±¾µØ´úÂëÔËÐС£

Çë²Î¿¼ErlangÍøÕ¾ÉϵĽ̡̳¢Îĵµ¡¢·¶ÀýµÈ¾«²Ê×ÊÔ´¡£


Ϊ
ʲôѡÔñErlang

ÄÚ½¨µÄ²¢ÐмÆËãÄ£ÐÍʹµÃErlang·Ç³£Êʺϱàд¶àÈËÔÚÏß·þÎñÆ÷¡£

¾ßÓÐÁ¼ºÃÉìËõÐԵĴóÐͶàÈ˺ǫ́ϵͳÓÃErlangÊÇÕâÑù¹¹½¨µÄ£ºÓɺܶ౻·ÖÅ䲻ͬÈÎÎñµÄ¡°½Úµã(Node)¡±×é³ÉµÄ¡°¼¯Èº(Cluster)¡±¡£Ò»¸öErlang½Úµã¾ÍÊÇÒ»¸öErlangÐéÄâ»úµÄʵÀý£¬Äã¿ÉÒÔÔÚһ̨»úÆ÷(·þÎñÆ÷£¬Ì¨Ê½»ú»òÕ߱ʼDZ¾µçÄÔÉÏÔËÐжà¸ö½Úµã¡£ÎÒÍÆ¼öÒ»¿éCPUÒ»¸ö½Úµã¡£

Erlang½Úµã×Ô¶¯¸ú×ÙËùÓÐÁ¬½Ó×ŵįäËû½Úµã¡£ÒªÌí¼ÓÒ»¸ö½ÚµãÄã½ö½öÐèÒª°ÑËüÖ¸ÏòÈκÎÒ»¸öÒѽ¨½Úµã¾Í¿ÉÒÔÁË¡£Ö»ÒªÕâÁ½¸ö½Úµã½¨Á¢ÁËÁ¬½Ó£¬ËùÓÐÆäËûµÄ½ÚµãÂíÉϾͻá¸ÐÓ¦µ½Ð¼ÓÈëµÄ½Úµã¡£

Erlang½ø³ÌʹÓýø³ÌIDÏòÆäËû½ø³Ì´«µÝ±¨ÎÄ£¬½ø³ÌID°üº¬×ÅÔËÐд˽ø³ÌµÄ½ÚµãµÄÐÅÏ¢¡£Òò´Ë½ø³Ì²»ÐèÒªÀí»áÕýÔÚÓëÆä½»Á÷µÄÆäËû½ø³Ìʵ¼ÊÔںδ¦ÔËÐС£Ò»×éÏ໥Á¬½ÓµÄErlang½Úµã¿ÉÒÔ¿´×÷ÊÇÒ»¸öÍø¸ñ¼ÆËãÌå»òÕßһ̨³¬¼¶¼ÆËã»ú¡£

½«´óÐͶàÈËÔÚÏßÓÎÏ·ÀïµÄÍæ¼Ò£¬NPCÒÔ¼°ÆäËû¸öÌå³éÏóΪºÜ¶à²¢ÐÐÔËÐеĽø³ÌÊÇ×îÀíÏëµÄ£¬µ«ÊÇͨ³£²¢ÐÐÔËËãµÄʵÏÖÈÃÈËÊ®·ÖÍ·ÌÛ¡£ErlangÌìÉú¾ÍÊǼò»¯²¢ÐмÆËãµÄʵÏÖ¡£

ErlangÓï·¨ÀïµÄ±ÈÌØ²Ù×÷Èöþ½øÖƲÙ×÷±äµÃÒì³£¼òµ¥£¬¼«´ó·¢»ÓÁËPerlºÍPythonµÄ´ò°ü/½â°ü½á¹¹¡£Ê¹µÃErlang·Ç³£ÊʺϲÙ×÷¶þ½øÖÆÍøÂçͨѶЭÒé¡£


OpenPokerµÄÌåϵ½á¹¹

OpenPokerÀïµÄÒ»ÇеÄÒ»Çж¼Êǽø³Ì¡£Íæ¼Ò£¬»úÆ÷ÈË£¬ÓÎÏ·£¬Ì§ÃæµÈµÈµÈµÈ£¬¶¼ÊÇÒ»¸ö¸ö½ø³Ì¡£Ã¿Ò»¸öÁ¬½Óµ½OpenPokerµÄ¿Í»§¶Ë¶¼ÓÐÒ»¸ö°çÑÝ¡°´úÀí¡±½ÇÉ«µÄÍæ¼Ò½ø³ÌÓÃÀ´´¦ÀíÍøÂçÏûÏ¢¡£È¡¾öÓÚÍæ¼ÒÊÇ·ñµÇ½£¬Ä³Ð©ÏûÏ¢±»ºöÂÔ¶øÓÐЩ±»´«µÝµ½´¦ÀíÓÎÏ·Âß¼­µÄ½ø³Ì¡£

ֽůÓÎÏ·½ø³ÌÊÇÒ»¸ö״̬»úËÞÖ÷£ºÓɶàÖÖÓÎϷ״̬µÄ¸÷ÖÖ״̬»úÄ£¿é×é³É¡£ÕâÑùÎÒµÄֽůÓÎÏ·½ø³Ì¿ÉÒÔÏòÀָ߻ýľһÑùËæÒâÌíש¼ÓÍß¡ª¡ªÖ»Òª¼ÓÈë״̬»ú¾Í¿ÉÒÔÌí¼ÓеÄֽůÓÎÏ·¡£´Ë·½°¸¿ÉÒԲο¼ÎÒдµÄ³õʼº¯Êý(ÔÚcardgame.erlÀï

ֽůÓÎϷ״̬»ú¸ù¾ÝĿǰÓÎÏ·µÄ״̬½ÓÊܲ»Í¬µÄÏûÏ¢¡£¶øÇÒÎÒÓÃÒ»¸ö¶ÀÁ¢µÄ½ø³ÇÀ´´¦ÀíͨÓÃÐÅÏ¢£¬±ÈÈç¸ú×ÙÍæ¼Ò״̬£¬Ì§ÃæÇé¿ö£¬¸÷ÖÖÏÞÖÆµÈµÈ¡£ÔÚÎҵıʼDZ¾µçÄÔÉÏÄ£Äâ27£¬000¸öÆË¿ËÓÎÏ·£¬»á²úÉú136,000¸öÍæ¼ÒºÍ´óÔ¼800£¬000¸ö½ø³Ì¡£

Õâ˵Ã÷ÁËΪʲôÎÒ¼«Á¦×¨×¢ÓÚʹÓÃOpenPokerΪÀýÌÖÂÛErlangÈçºÎÇáËɵÄʵÏÖ¿ÉÉìËõÐÔ£¬ÈÝ´íÐÔ£¬ºÍ¸ºÔØÆ½ºâ¡£´Ë·½°¸²»½ö½ö¾ÖÏÞÓÚÆË¿ËֽůÓÎÏ·¡£ÏàͬµÄ»úÖÆÍêÈ«¿ÉÒÔʤÈÎÆäËûÀàÐÍ´ó¹æÄ£¿ÉÉìËõ¶àÈËÔÚÏߺǫ́ϵͳ£¬±ãÒ˼òµ¥Ò»µã¶ùÒ²²»ÓôÃÆ£¡


¿ÉÉìËõÐÔ

ÎÒʹÓöà²ãÌåϵʵÏÖ¸ßÉìËõÐԺ͸ºÔØÆ½ºâ¡£µÚÒ»²ãÊÇÍø¹Ø½Úµã¡£µÚ¶þ²ãÊÇÓÎÏ··þÎñ¶Ë½Úµã£¬×îºóÒ»²ãÊÇMnesiaÖ÷½Úµã¡£

MnesiaÊÇErlangµÄʵʱ·Ö²¼Ê½Êý¾Ý¿âϵͳ¡£Mnesia FAQ½âÊ͵úÜÏêϸ£¬ËüÊÇÒ»¸ö¸ßËÙ£¬Öظ´ÐÔ£¬ÄÚ´æ×¤ÁôµÄÊý¾Ý¿â¡£Erlang±¾ÉíûÓжÔÏóÖ§³Öµ«ÊÇMnesia¿ÉÒÔ±»¿´×÷ÊÇÃæÏò¶ÔÏóµÄÒòΪËü´æÖüËùÓÐErlangÊý¾Ý¡£

ÓÐÁ½ÖÖMnesia½Úµã£º·ÃÎÊ´ÅÅ̵ĺͲ»·ÃÎÊ´ÅÅ̵ġ£ÎÞÂÛÔõÑù£¬ËùÓÐMnesia½ÚµãÔÚÄÚ´æÖд洢Êý¾Ý¡£OpenPokerÀïµÄMnesia½ÚµãÊÇÓÃÀ´·ÃÎÊ´ÅÅ̵ġ£Íø¹ØºÍÓÎÏ··þÎñ²ãÖ»²Ù×÷Äڴ棬Æô¶¯ºó´ÓMnesia·ÃÎÊÊý¾Ý¿â¡£

ErlangÐéÄâ»úÓÐÒ»Ì׺ܷ½±ãµÄÃüÁîÐвÎÊýÀ´Í¨ÖªMnesiaÖ÷Êý¾Ý¿â´æÔÚÄÄÀï¡£ÈκÎеÄMnesia½ÚµãÖ»ÒªºÍÖ÷½Úµã½¨Á¢ÁËÁ¬½Ó£¬ÐµĽڵãÂíÉϳÉΪ¼¯ÈºµÄÒ»²¿·Ö¡£

¼ÙÉèÖ÷½ÚµãλÓÚappleºÍorangeÁ½Ì¨Ö÷»úÉÏ£¬ÄÇôÌí¼ÓеÄÍø¹Ø½Úµã£¬ÓÎÏ··þÎñ½ÚµãµÈµÈµ½ÄãµÄOpenPoker¼¯Èº½ö½öÐèÒªÈçÏÂÃüÁîÐÐÆô¶¯£º

erl -mnesia extra_db_nodes \['db@apple','db@orange'\] -s mnesia start
-s mnesia start Ò²¿ÉÒÔÓÃErlang¿ØÖÆÌ¨Æô¶¯Mnesia:
erl -mnesia extra_db_nodes \['db@apple','db@orange'\]
Erlang (BEAM) emulator version 5.4.8 [source] [hipe] [threads:0]

Eshell V5.4.8 (abort with ^G)
1> mnesia:start().
ok

OpenPokerÔÚMnesiaÊý¾Ý±íÀï±£´æÅäÖÃÐÅÏ¢£¬´ËÐÅÏ¢ÔÚMnesiaÆô¶¯µÄʱºò×Ô¶¯±»Ð½ڵãÏÂÔØ¡£ÍêÈ«ÁãÅäÖã¡

ÈÝ´íÐÔ

ÌíÖü¸¸ö±ãÒ˵ÄLinuxϵͳµ½ÎҵķþÎñÆ÷×飬OpenPoker¿ÉÒÔÒª¶à´ó¹æÄ£Óжà´ó¹æÄ£¡£×éºÏÒ»´ò1U·þÎñÆ÷ϵͳ¿ÉÒÔÇáËÉʤÈÎÎåÊ®ÍòÉõÖÁÒ»°ÙÍòÍæ¼ÒͬʱÔÚÏß¡£µ±È»²»½ö½öÊÇֽůÓÎÏ·£¬¶ÔÓÚÆäËû¶àÈËRPGÍøÓÎ(MMORPG)Ò²ÊÇÒ»ÑùµÄ¡£

ÎÒ¿ÉÒÔÖ¸Åɼ¸¸ö·þÎñÆ÷×öÍø¹Ø½Úµã£¬ÁíÍ⼸¸ö×öÊý¾Ý¿â½Úµã·ÃÎÊ´æ´¢½éÖÊÉϵÄÊý¾Ý£¬È»ºóʣϵÄһЩ×öÓÎÏ··þÎñÆ÷¡£ÎÒ»¹¿ÉÒÔÏÞÖÆµ¥Ì¨·þÎñÆ÷×î¸ß½ÓÄÉÎåǧÍò¼ÒͬʱÔÚÏߣ¬ËùÒÔÈκÎһ̨µ±»ú£¬×î¶à5ǧ¸öÍæ¼ÒÊÜÓ°Ïì¡£

ÁíÍâÒªÖ¸³öµÄÊÇÈκÎһ̨ÓÎÏ··þÎñÆ÷µ±»ú¶¼²»»áÓÐÊý¾ÝËð»ÙÒòΪËùÓÐMnesiaµÄÊý¾Ý·ÃÎʲÙ×÷¶¼ÊÇÓɶà¸öÓÎÏ·£¬Mnesia½Úµãʵʱ±¸·ÝµÄ¡£

¿¼Âǵ½Ä³Ð©Ç±ÔÚ´íÎó£¬ÓÎÏ·¿Í»§¶ËÐèÒª×öһЩ¸¨Öú¹¤×÷ÈÃÍæ¼Ò˳»¬µÄÖØÐÂÁ¬½Óµ½OpenPoker·þÎñÆ÷¼¯Èº¡£Ã¿µ±¿Í»§¶Ë·¢ÏÖÍøÂç´íÎ󣬾ͻ᳢ÊÔÁ¬½ÓÍø¹Ø½Úµã£¬Í¨¹ý½ÓÁ¦ÍøÂç°üµÃµ½Ò»¸öеÄÓÎÏ··þÎñ½ÚµãµØÖ·È»ºóÖØÐÂÁ¬½Ó¡£ÕâÀïÐèÒªµã¼¼ÇÉÒòΪ²»Í¬µÄÇé¿öÒª²»Í¬¶Ô´ý£º

OpenPoker»®·ÖÈçÏÂÐèÒªÖØÐÂÁ¬½ÓµÄÇé¿ö£º

  1. ÓÎÏ··þÎñÆ÷µ±»ú

  2. ¿Í»§¶Ëµ±»ú»òÕßÍøÂçÑÓ³Ù³¬Ê±

  3. Íæ¼Ò»»ÁíÍâÒ»¸öÍøÂçÁ¬½ÓÔÚÏß

  4. Íæ¼ÒÔÚÓÎÏ·ÖÐÇл»ÁíÒ»¸öÍøÂçÁ¬½Ó

×î³£¼ûµÄ¾ÍÊǿͻ§¶ËÒòÎªÍøÂç´íÎó¶ø¶Ï¿ªÁ¬½Ó¡£×î²»³£¼ûµ«ÊÇ»¹ÊÇÓпÉÄܵÄÊÇͬһ¸ö¿Í»§¶ËÔÚÓÎÏ·ÖеÄʱºò´ÓÁíÒ»¸öµçÄÔ³¢ÊÔÁ¬½Ó¡£

ÿ¸öOpenPokerÓÎÏ·»º´æ·¢Ë͸øÍæ¼ÒµÄÊý¾Ý°ü£¬Ã¿´Î¿Í»§¶ËÖØÐÂÁ¬½Ó¶¼»áÊÕµ½×ÔÓÎÏ·¿ªÊ¼µÄËùÓÐÊý¾Ý°üÈ»ºóÔÙ¿ªÊ¼Õý³£½ÓÊÜ¡£OpenPokerʹÓÃTCPÁ¬½ÓËùÒÔ²»Óÿ¼ÂÇÊý¾Ý°üµÄ·¢ËÍ˳Ðò¡ª¡ªËùÓÐÊý¾Ý°ü±£Ö¤Êǰ´Ë³ÐòÊÕµ½µÄ¡£

ÿ¸ö¿Í»§¶ËÁ¬½ÓÓÉÁ½¸öOpenPoker½ø³Ì×é³É£ºÌ×½Ó×Ö½ø³Ì»¹ÓÐÍæ¼Ò½ø³Ì¡£»¹ÓÐÒ»¸öÊÜÏÞÖÆµÄ·Ã¿Í½ø³Ì±»Ê¹ÓÃÖ±ÖÁÍæ¼Ò³É¹¦µÇ½£¬·Ã¿Í²»ÄܼÓÈëÓÎÏ·¡£Ì×½Ó×Ö½ø³ÌËäÍøÂçÖж϶øÍ£Ö¹£¬µ«ÊÇÍæ¼Ò½ø³ÌÈÔÈ»±£³Ö»î¶¯¡£

Íæ¼Ò½ø³Ì·¢ËÍÓÎÏ·Êý¾Ý°üµÄʱºò¿ÉÒÔÕì²âµ½ÒѾ­ÖжϵÄÌ×½Ó×Ö½ø³Ì£¬´Ëʱ»á½øÈë×Ô¶¯ÔËÐÐ״̬»òÕßÔÝͣ״̬¡£µÇ½´úÂë»áÔÚÖØÐÂÁ¬½ÓµÄʱºòͬʱ²Î¿¼Ì×½Ó×Ö½ø³ÌºÍÍæ¼Ò½ø³Ì¡£ÓÃÀ´Õì²âµÄ´úÂëÈçÏ£º

login({atomic, [Player]}, [_Nick, Pass|_] = Args) 
when is_record(Player, player) ->
Player1 = Player#player {
socket = fix_pid(Player#player.socket),
pid = fix_pid(Player#player.pid)
},
Condition = check_player(Player1, [Pass],
[
fun is_account_disabled/2,
fun is_bad_password/2,
fun is_player_busy/2,
fun is_player_online/2,
fun is_client_down/2,
fun is_offline/2
]),
...

ÆäÖеĸ÷¸öÌõ¼þÊÇÕâôдµÄ£º

is_player_busy(Player, _) ->
{Online, _} = is_player_online(Player, []),
Playing = Player#player.game /= none,
{Online and Playing, player_busy}.

is_player_online(Player, _) ->
SocketAlive = Player#player.socket /= none,
PlayerAlive = Player#player.pid /= none,
{SocketAlive and PlayerAlive, player_online}.

is_client_down(Player, _) ->
SocketDown = Player#player.socket == none,
PlayerAlive = Player#player.pid /= none,
{SocketDown and PlayerAlive, client_down}.

is_offline(Player, _) ->
SocketDown = Player#player.socket == none,
PlayerDown = Player#player.pid == none,
{SocketDown and PlayerDown, player_offline}.

ҪעÒâloginº¯ÊýÊ×ÏÈÒª×öµÄÊÇÐÞ¸´ÒÑʧ°ÜµÄ½ø³ÌID¡£ÕâÑù¼ò»¯ÁË´¦Àí¹ý³Ì£¬´úÂëÈçÏ£º

fix_pid(Pid)
when is_pid(Pid) ->
case util:is_process_alive(Pid) of
true ->
Pid;
_ ->
none
end;

fix_pid(Pid) ->
Pid.

ºÍ:

-module(util).

-export([is_process_alive/1]).

is_process_alive(Pid)
when is_pid(Pid) ->
rpc:call(node(Pid), erlang, is_process_alive, [Pid]).

ErlangÀïµÄ½ø³ÌID°üº¬ÔËÐнø³ÌµÄ½ÚµãµÄId. is_pid(Pid)·µ»Ø²ÎÊýÊÇ·ñΪһ¸ö½ø³ÌIdµ«ÊÇÎÞ·¨ÖªµÀ½ø³ÌÊÇ·ñÒÑÖжϡ£ErlangµÄÄÚ½¨º¯Êýerlang:is_process_alive(Pid)¿ÉÒÔ×öµ½¡£is_process_aliveÒ²¿ÉÒÔÓÃÀ´¼ì²éÔ¶³Ì½Úµã£¬ÓÃÆðÀ´ÊÇÃ»Çø±ðµÄ¡£

¸ü·½±ãµÄÊÇ£¬ÎÒÃÇ¿ÉÒÔÓÃErlang RPC¹¦ÄÜ£¬ÁªºÏnode(pid)À´µ÷ÓÃÔ¶³Ì½ÚµãµÄis_process_alive()¡£ÓÃÆðÀ´ºÍ·ÃÎʱ¾µØ½ÚµãÒ»Ñù£¬ËùÒÔÉÏÃæµÄ´úÂëʵ¼ÊÉÏÒ²ÊÇÈ«¾Ö·Ö²¼Ê½½ø³Ì¼ì²é¡£

×îºóÊ£µÄ¹¤×÷¾ÍÊÇ´¦ÀíµÇ½µÄ¸÷ÖÖÇé¿öÁË¡£×îÖ±½ÓµÄÇé¿öÊÇÍæ¼Ò´¦ÓÚÀëÏß״̬ȻºóÆô¶¯ÁËÒ»¸öÍæ¼Ò½ø³Ì£¬Á¬½ÓÍæ¼Ò½ø³Ìµ½Ì×½Ó×Ö½ø³Ì£¬È»ºó¸üÐÂÍæ¼ÒÊý¾Ý¡£

login(Player, player_offline, [Nick, _, Socket]) ->
{ok, Pid} = player:start(Nick),
OID = gen_server:call(Pid, 'ID'),
gen_server:cast(Pid, {'SOCKET', Socket}),
Player1 = Player#player {
oid = OID,
pid = Pid,
socket = Socket
},
{Player1, {ok, Pid}}.

Èç¹ûµÇ½ÐÅÏ¢²»ÕýÈ·¾Í·µ»Ø´íÎóÈ»ºó¼Ç¼µÇ½³¢ÊÔ´ÎÊý¡£Èç¹û³¢ÊÔ³¬¹ýÒ»¶¨´ÎÊý£¬¿ÉÒÔÓÃÈçÏ´úÂë¹Ø±ÕÕË»§£º

login(Player, bad_password, _) ->
N = Player#player.login_errors + 1,
{atomic, MaxLoginErrors} =
db:get(cluster_config, 0, max_login_errors),
if
N > MaxLoginErrors ->
Player1 = Player#player {
disabled = true
},
{Player1, {error, ?ERR_ACCOUNT_DISABLED}};
true ->
Player1 = Player#player {
login_errors = N
},
{Player1, {error, ?ERR_BAD_LOGIN}}
end;

login(Player, account_disabled, _) ->
{Player, {error, ?ERR_ACCOUNT_DISABLED}};

×¢ÏúÓû§Ê±£¬ÏÈÓÃObjectIDÕÒµ½Íæ¼Ò½ø³ÌID£¬È»ºóÍ£Ö¹Íæ¼Ò½ø³Ì²¢¸üÐÂÊý¾Ý¿â¼Ç¼£º

logout(OID) ->
case db:find(player, OID) of
{atomic, [Player]} ->
player:stop(Player#player.pid),
{atomic, ok} = db:set(player, OID,
[{pid, none},
{socket, none}]);
_ ->
oops
end.

Èç¹û×¢Ïú²»Õý³££¬¿ÉÒÔ·Ö±ðÕë¶Ô¸÷ÖÖÖØÐÂÁ¬½ÓÌõ¼þ´¦Àí¡£Èç¹ûÍæ¼ÒÔÚÏßÈ´´¦ÓÚÏÐÖÃ״̬£¬±ÈÈç˵ͣÔÚ´óÌü»òÕßÕýÅÔ¹ÛÒ»¸öÓÎÏ·(¿ÉÄÜÔÚºÈ×ÅÆ¿°ÙÍþ£¬Î¹Î¹£¡£¬È»ºó³¢ÊÔ´ÓÁíһ̨µçÄÔÁ¬½Ó£¬ÄÇô³ÌÐòÏȽ«ÆäµÇ³öÈ»ºóÖØÐ½«ÆäµÇÈ룬¾ÍÏñ´ÓÀëÏß״̬ϵÇÈëÒ»Ñù£º

login(Player, player_online, Args) ->
logout(Player#player.oid),
login(Player, player_offline, Args);

Èç¹ûÍæ¼ÒÕýÔÚÏÐÖöø¿Í»§¶Ë¶Ï¿ªÁ¬½ÓÁË£¬ÄÇôֻÐèÒªÔڼǼÀïÌæ»»ËûµÄÌ×½Ó×Ö½ø³ÌµØÖ·È»ºóÍ¨ÖªÍæ¼Ò½ø³ÌеÄÌ×½Ó×Ö£º

login(Player, client_down, [_, _, Socket]) ->
gen_server:cast(Player#player.pid, {'SOCKET', Socket}),
Player1 = Player#player {
socket = Socket
},
{Player1, {ok, Player#player.pid}};

Èç¹ûÍæ¼ÒÔÚÓÎÏ·ÖУ¬ÄÇô³ýÁËÔËÐÐÉÏÃæÄǶÎÒÔÍ⣬֪ͨÓÎÏ·ÖØÐ·¢Ë͹ýÍùʼþ¡£

login(Player, player_busy, Args) ->
Temp = login(Player, client_down, Args),
cardgame:cast(Player#player.game,
{'RESEND UPDATES', Player#player.pid}),
Temp;

×ܶøÑÔÖ®£¬°üº¬×ÅʵʱÈßÓàÊý¾Ý¿â£¬ÖÇÄÜÖØÁ¬µÄ¿Í»§¶Ë£¬»¹ÓÐһЩ¾«Çɵĵǽ´úÂëµÄÕâÒ»Ì××éºÏ·½°¸¿ÉÒÔÌṩ¸ß¶ÈµÄÈÝ´íÐÔ£¬¶øÇÒ¶ÔÓÚÍæ¼ÒÀ´Ëµ£¬ÊÇ͸Ã÷µÄ¡£


¸ºÔØÆ½ºâ

ÎÒ¿ÉÒÔÓÃÏë¶àÉپͶàÉٵķþÎñÆ÷½Úµã×齨ÎÒµÄOpenPoker¼¯Èº¡£Ò²¿ÉÒÔ×ÔÓɵ÷Å䣬±ÈÈç˵ÿ¸ö·þÎñÆ÷½Úµã5000¸öÍæ¼Ò£¬È»ºóÔÚÕû¸ö¼¯ÈºÖÐÆ½Ì¯¹¤×÷¸ºÔØ¡£ÎÒ¿ÉÒÔÔÚÈκÎʱºòÌí¼ÓеķþÎñÆ÷½Úµã£¬Ð½ڵã×Ô¼º»á×Ô¶¯ÅäÖò¢¿ªÊ¼½ÓÊÜÐÂÍæ¼Ò¡£

Íø¹Ø½Úµã¿ØÖÆ×ÅÏòOpenPoker¼¯ÈºÀïµÄËùÓл½Úµãƽºâ¸ºÔØ¡£Íø¹Ø½ÚµãµÄ×÷ÓþÍÊÇËæ»úÑ¡ÔñÒ»¸ö·þÎñÆ÷½Úµã£¬²éѯÒÑÁ¬½ÓÍæ¼ÒÊý£¬Ö÷»úµØÖ·£¬¶Ë¿ÚµÈµÈ¡£Ö»ÒªÍø¹Ø½ÚµãÕÒµ½Ò»¸öÓÎÏ··þÎñÆ÷δ´ïµ½¸ºÔØ×î´óÖµ£¬Ëü¾Í°Ñ·þÎñÆ÷µÄµØÖ·ÐÅÏ¢´«µÝ¸ø¿Í»§¶ËÈ»ºó¹Ø±ÕÁ¬½Ó¡£

ºÜÃ÷ÏÔÍø¹Ø½Úµã¹¤×÷Á¿²»´ó£¬¶øÇÒÖ¸ÏòÕâ¸ö½ÚµãµÄÁ¬½Ó¶¼ÊÇ˲ʱµÄ¡£Äã¿ÉÒÔËæ±ãÓøö±ãÒË»úÆ÷×öÄãµÄÍø¹Ø½Úµã¡£

½ÚµãÒ»°ãÓ¦¸ÃÊÇÒ»¶ÔÒ»¶ÔµÄ£¬ÕâÑùÈç¹ûÒ»¸öʧ°Ü£¬ÁíÒ»¸ö¿ÉÒÔÂíÉÏÌæ²¹¡£Äã¿ÉÒÔ²ÉÓÃRound-robin DNSÀ´ÅäÖöà¸öÍø¹Ø½Úµã¡£

ÄÇÃ´Íø¹ØÈçºÎÕÒµ½ÓÎÏ··þÎñÆ÷ÄØ£¿

OpenPoker²ÉÓÃErlangµÄ·Ö²¼Ê½½ø³Ì×é(Distributed Named Process GroupsÀ´·Ö×éÓÎÏ··þÎñÆ÷¡£ËùÓнڵ㶼¿ÉÒÔ·ÃÎÊ×éÁÐ±í£¬ÕâÒ»¹ý³ÌÊÇ×Ô¶¯µÄ¡£ÐµÄÓÎÏ··þÎñÆ÷Ö»Ðè¼ÓÈë·þÎñÆ÷×顣ij¸ö½Úµãµ±»ú×Ô¶¯´Ó×éÁбíÀïÌÞ³ý¡£

²éÕÒ·þÎñÍæ¼Ò×îÉٵķþÎñÆ÷µÄ´úÂëÈçÏ£º

find_server(MaxPlayers) ->
case pg2:get_closest_pid(?GAME_SERVERS) of
Pid when is_pid(Pid) ->
{Time, {Host, Port}} = timer:tc(gen_server, call, [Pid, 'WHERE']),
Count = gen_server:call(Pid, 'USER COUNT'),
if
Count < MaxPlayers ->
io:format("~s:~w: ~w players~n", [Host, Port, Count]),
{Host, Port};
true ->
io:format("~s:~w is full...~n", [Host, Port]),
find_server(MaxPlayers)
end;
Any ->
Any
end.

pg2:get_closest_pid()·µ»ØÒ»¸öËæ»úµÄÓÎÏ··þÎñÆ÷½ø³ÌID£¨Íø¹Ø½ÚµãÉϲ»ÔËÐÐÈκÎÓÎÏ··þÎñÆ÷£©¡£È»ºóÏò·µ»ØµÄ·þÎñÆ÷²éѯµØÖ·¶Ë¿ÚÒÔ¼°Ä¿Ç°Á¬½ÓµÄÍæ¼ÒÊý¡£Ö»ÒªÎ´×ã×î´ó¸ºÔضî¾Í°ÑµØÖ··µ»Ø¸øµ÷Óýø³Ì£¬·ñÔò¼ÌÐø²éÕÒ¡£


¶à¹¦Äܲå×ùÖмä¼þ

OpenPokerÊÇÒ»¸ö¿ªÔ´Èí¼þ£¬ÎÒ×î½üÒ²ÕýÔÚ½«ÆäͶÏòÐí¶àÆåÅÆÀàÔËÓªÉÌ¡£ËùÓÐÉ̼Ҷ¼´æÔÚÈÝ´íÐԺͿÉÉìËõÐÔµÄÎÊÌ⣬¼´Ê¹ÓÐЩÒѾ­¾­¹ýÁ˳¤ÄêµÄ¿ª·¢Î¬»¤¡£ÓÐЩÒѾ­ÖØÐ´ÁË´úÂ룬¶øÓÐЩ²Å¸Õ¸ÕÆð²½¡£ËùÓÐÉ̼Ҷ¼ÔÚJavaÌåϵÉÏ´ó±ÊͶÈ룬ËùÒÔËûÃDz»Ô¸Òâ»»µ½ErlangÒ²ÊÇ¿ÉÒÔÀí½âµÄ¡£

µ«ÊÇ£¬¶ÔÎÒÀ´ËµÕâÊÇÒ»ÖÖÉÌ»ú¡£ÎÒÔ½ÊÇÉîÈëÑо¿£¬Ô½·¢ÏÖErlang¸üÊʺÏÌṩһ¸ö¼òµ¥Ö±½ÓÈ´ÓÖ¸ßЧ¿É¿¿µÄ½â¾ö·½°¸¡£ÎÒ°ÑÕâ¸ö½â¾ö·½°¸¿´³ÉÒ»¸ö¶à¹¦Äܲå×ù£¬¾ÍÏñÄãÏÖÔÚµçÔ´²åÍ·ÉÏÁ¬×ŵÄÒ»Ñù¡£

ÄãµÄÓÎÏ··þÎñÆ÷¿ÉÒÔÏñ¼òµ¥µÄµ¥Ò»Ì×½Ó×Ö·þÎñÆ÷Ò»ÑùµÄд£¬Ö»ÓÃÒ»¸öÊý¾Ý¿âºǫ́¡£Êµ¼ÊÉÏ£¬¿ÉÄܱÈÄãÏÖÔÚµÄÓÎÏ··þÎñÆ÷дµÃ»¹Òª¼òµ¥¡£ÄãµÄÓÎÏ··þÎñÆ÷¾ÍºÃ±ÈÒ»¸öµçÔ´²åÍ·£¬¶àÖÖµçÔ´²åÍ·½ÓÔÚÎҵIJåÏß°åÉÏ£¬¶øÍæ¼Ò¾Í´ÓÁíÒ»¶ËÁ÷Èë¡£

ÄãÌṩÓÎÏ··þÎñ£¬¶øÎÒÌṩ¿ÉÉìËõÐÔ£¬¸ºÔØÆ½ºâ£¬»¹ÓÐÈÝ´íÐÔ¡£ÎÒ±£³ÖÍæ¼ÒÁ¬µ½²åÏß°åÉϲ¢¼àÊÓÄãµÄÓÎÏ··þÎñÆ÷ÃÇ£¬ÔÚÐèÒªµÄʱºòÖØÆôÈκÎÒ»¸ö¡£ÎÒ»¹¿ÉÒÔÔÚij¸ö·þÎñÆ÷µ±µôµÄÇé¿öϰÑÍæ¼Ò´ÓÒ»¸ö·þÎñÆ÷Çл»µ½ÁíÒ»¸ö£¬¶øÄã¿ÉÒÔËæÊ±²åÈëеķþÎñÆ÷¡£

Õâôһ¸ö¶à¹¦ÄܲåÏß°åÖмä¼þ¾ÍÏñÒ»¸öºÚÏ»×ÓÉèÖÃÔÚÍæ¼ÒÓë·þÎñÆ÷Ö®¼ä£¬¶øÇÒÄãµÄÓÎÏ·´úÂë²»ÐèÒª×ö³öÈκÎÐ޸ġ£Äã¿ÉÒÔÏíÓÃÕâ¸ö·½°¸´øÀ´µÄ¸ßÉìËõÐÔ£¬¸ºÔØÆ½ºâ£¬¿ÉÈÝ´íÐԵȺô¦£¬Óë´Ëͬʱ½ÚԼͶ×ʲ¢Ð´½ö½öÐÞ¸ÄһС²¿·ÖÌåϵ½á¹¹¡£

Äã¿ÉÒÔ½ñÌì¾Í¿ªÊ¼Ð´Õâ¸öErlangµÄÖмä¼þ£¬ÔÚÒ»¸öÌØ±ðΪTCPÁ¬½ÓÊý×öÁËÓÅ»¯µÄLinux»úÆ÷ÉÏÔËÐУ¬°ÑÕą̂»úÆ÷·Åµ½¹«ÖÚÍøÉϵÄͬʱ±£³ÖÄãµÄÓÎÏ··þÎñÆ÷Ⱥ×éÔÚ·À»ðǽ±³ºó¡£¾ÍËãÄã²»´òËãÓã¬ÎÒÒ²½¨ÒéÄã³é¿Õ¿´¿´Erlang¿¼ÂÇÒ»ÏÂÈçºÎ¼ò»¯ÄãµÄ¶àÈËÔÚÏß·þÎñÆ÷¼Ü¹¹¡£¶øÇÒÎÒËæÊ±Ô¸Òâ°ï棡