【问题标题】:Poker lobby architecture扑克大厅建筑
【发布时间】:2012-04-27 23:27:05
【问题描述】:

我已经使用 WCF net.tcp 和 WPF 作为前端创建了一个在线扑克系统。它工作得很好,但我觉得当我将前端转换为 Silverlight 时,我可以改进一些东西。

我对其他建筑师的一个问题是游戏大厅应该如何刷新?扑克游戏大厅会不断更新统计数据,例如玩家数量、每小时手数和翻牌百分比。

由于在任何给定时间都可能有数百个游戏正在进行,我不太确定每 5 秒(轮询)返回整个游戏列表是否最佳。我正在考虑使用增量查询,因为许多游戏不会有状态更新(例如:桌上没有玩家)。

我正在考虑使用更新时间,因此每次客户端(可能是数百甚至数千!)轮询时,只会返回在 5、10 或更长时间内更新的记录。

游戏大厅客户端当然会负责协调新数据,但我认为这有助于减轻游戏服务器的一些负担。

有什么想法吗?

【问题讨论】:

    标签: wpf silverlight wcf architecture poker


    【解决方案1】:

    您可以选择客户端在服务器上注册以进行循环更新的方法。因此,服务器将提供一个服务合同和一个客户端必须实现的回调合同(双工合同)。详情请见here

    另一方面,从 Silverlight 客户端使用双工合同可能很困难(我不确定这是否可能),因此使用更新时间间隔进行轮询是一种合法的方法。服务器应发送当前时间戳以及轮询周期的响应数据,客户端将在其下一个请求中将其发回以指示何时请求更新数据。避免比较客户端和服务器时间。

    【讨论】:

    • 有趣的是你应该提到双工。我通过 IIS7 和 net.tcp 对实际游戏使用 WCF 双工操作。我不确定发布和订阅是否是大厅部分的最佳架构,因为您需要做很多事情来处理负载平衡、故障转移等。双工操作。此外,大厅会在显示时不断请求信息。当大厅窗口最小化时,我关闭了轮询间隔。
    • 你说得对,Pub/Sub 开销很大。事实上,在我目前正在从事的一个基于 WCF 的项目中,我刚刚决定反对它,支持循环轮询:-)
    【解决方案2】:
    <Window x:Class="TestListUpdate.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <ListView Name="listView1">
                <ListView.View>
                    <GridView>
                        <GridViewColumn Width="140" Header="Name" DisplayMemberBinding="{Binding Value.Name}" />
                        <GridViewColumn Width="140" Header="Creator" DisplayMemberBinding="{Binding Value.Creator}" />
                        <GridViewColumn Width="140" Header="Publisher" DisplayMemberBinding="{Binding Value.Publisher}" />
                    </GridView>
                </ListView.View>
            </ListView>
        </Grid>
    </Window>
    
    
    namespace TestListUpdate
    {
        /// <summary>
        /// Interaction logic for Window1.xaml
        /// </summary>
        public partial class Window1 : Window
        {
            Dictionary<int, GameData> _gameData = null;
    
            // This is a test, real data will be retrieved via a web service
            List<GameData> _updates = null;
    
            public Window1()
            {
                InitializeComponent();
    
                // This is the original data bound to the ListView control
                this._gameData = new Dictionary<int, GameData>();
                this._gameData.Add(1, new GameData { Id = 1, Creator = "ABC", Name = "One", Publisher = "123" });
                this._gameData.Add(2, new GameData { Id = 2, Creator = "DEF", Name = "Two", Publisher = "456" });
                this._gameData.Add(3, new GameData { Id = 3, Creator = "GHI", Name = "Three", Publisher = "789" });
                this._gameData.Add(4, new GameData { Id = 4, Creator = "JKL", Name = "Four", Publisher = "abc" });
                this._gameData.Add(5, new GameData { Id = 5, Creator = "MNO", Name = "Five", Publisher = "def" });
    
                // This is test data, some Ids are duplicates of the original data above
                // other items represent new items
                this._updates = new List<GameData>();
                this._updates.Add(new GameData { Id = 2, Creator = "DDD", Name = "Two", Publisher = "123" });
                this._updates.Add(new GameData { Id = 3, Creator = "TTT", Name = "Three", Publisher = "456" });
                this._updates.Add(new GameData { Id = 5, Creator = "FFF", Name = "Five", Publisher = "789" });
                this._updates.Add(new GameData { Id = 6, Creator = "XXX", Name = "Six", Publisher = "abc" });
                this._updates.Add(new GameData { Id = 7, Creator = "VVV", Name = "Seven", Publisher = "def" });
    
                System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
                timer.Interval = new TimeSpan(0, 0, 5);
                timer.Tick += new EventHandler(timer_Tick);
                timer.Start();
            }
    
            void timer_Tick(object sender, EventArgs e)
            {
                // Get a list of Ids from the new data
                var ids = (from l in this._updates
                           select l.Id);
    
                // Get a list of items that have matching Ids,
                // this data will be updated
                var updates = (from g in this._gameData
                               where ids.Contains(g.Value.Id)
                               select g);
    
                // Update the current items
                for (int i = 0; i < updates.Count(); ++i)
                {
                    KeyValuePair<int, GameData> kvp = updates.ElementAt(i);
                    kvp.Value.Publisher = DateTime.Now.ToLongTimeString();
                }
    
                // This represents new items to add
                this._gameData = this._gameData.Concat(
                        (from n in this._updates
                         where !this._gameData.ContainsKey(n.Id)
                         select n).ToDictionary(a => a.Id, a => a)
                     ).ToDictionary(q => q.Key, q => q.Value);
    
                // This is a simple trick to rebind the ListView control
                this.listView1.ItemsSource = null;
                this.listView1.ItemsSource = GameList;
            }
    
            // Databinding property
            public Dictionary<int, GameData> GameList
            {
                get { return this._gameData; }
            }
        }
    
        // Data class
        public class GameData
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Creator { get; set; }
            public string Publisher { get; set; }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      相关资源
      最近更新 更多