科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件高级WinSock多人游戏编程技术

高级WinSock多人游戏编程技术

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

多人网络游戏中如何避免迟延是一个比较重要的话题。作为多人网络游戏开发者,我们总是努力使事情做得更快,减少迟延以获得更多的带宽。

作者:佚名 来源:论坛 2007年10月20日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
6、在游戏中使用多播(Uses of Multicasting in Games)

  我能立刻想到两个用途。其一是减轻或避免服务器不得不重复发出的数据数量,另一个有趣的用途是提供一个用于查找网络中其他玩家的服务器无关通用接口。

  比如:有两个玩家想在一个大型网络中一起玩游戏,但他们不知道各自的IP地址也不知道是否有其他玩家存在。通常连接两个玩家的方法是:

  玩家发送一个广播消息给整个网络,然而这会造成巨大的网络流量同时有可能受到子网的限制。所以在互联网上进行广播是不允许的。

  所有玩家连接到一个主服务器的IP地址,在这里他们就能知道其他玩家的存在。这样服务器的开销很大,同步也难以得到保证。

  当玩家进入一个聊天房间希望找到其他玩家并一起游戏,这并不需要连接所有其他不在同一个房间的玩家,这个查找其他玩家的过程需要花费一些时间。

  这里我们有一个涉及到一方和多播的另一方的老问题(A如何找到B)。多播组通常有一个确定的地址即服务器的地址,它必定100%在线,可以认为它在连接和发送方面不需要花费其他开销。游戏客户端简单的连接到多播组,多播一个要加入游戏的信息。服务端将它的可见性直接(不用多播以节省带宽)宣告给多播组中的其他客户端。

  当然,这里有一个叫做itsy-bitsy的技术问题需要解决,但这个想法是够酷的。TTL控制允许我们查询路由范围,所以我们可以指定是发送给局域网或是校园网或是全国范围。是不是够酷了?

  唯一问题(见“不足之处”那节)是ISP和网络对多播的支持。所以最好的方法是将多播功能作为游戏的一个选项(虽然我希望将来多播能得到100%的支持)。如何将多播作为一个选项与游戏结合起来呢?接着看。

  7、让游戏与多播结合起来(Integrating Multicasting into Games)

  那么,我们从何处开始呢?有很多不同类型的网络游戏,这里我不想过多解释如何将多播与各种类型的游戏如何结合,只是给出一些关于解决客户端和服务端关系的想法。

  首先,最好保留你已经写的网络部分的代码,当你要加入多播支持时首先确认你确实需要否则不必改动你已写好的代码。

  添加多播支持时,可以和你原先的代码写在一块或者做成和原先代码分开成两部分,然后加入一个开关选项供使用者选择,这样,当能支持多播时就可以开启多播功能,不支持多播时就可以关闭多播功能。

  这就是平行结合方法,原有的普通网络代码可以照常工作,而多播代码只在多播得到支持时运行。那么我们如何检查多播是否得到支持呢?可以通过检查setsockopt()函数返回值来实现:

  nRet = setsockopt(hUDPSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
           (char*)&mreq, sizeof(mreq));
  if(WSAESOCKTNOSUPPORT == nRet)
  {
    // Multicasting not supported. Damn.
  }

  客户端和服务端的关系是一个游戏的两个部分。那么当服务端支持多播而客户端不支持多播该怎么办呢?服务端如何知道哪个客户端支持多播而哪个客户端不支持多播呢?客户端首先检查自己是否支持多播然后连接到服务端并告知服务端,服务端通常有一个客户端的列表,我们可以在列表中加入一个布尔变量来表示客户端是否支持多播:

  struct Client
  {
    SOCKADDR_IN addrRemote;
    /* ... Game specific info here ...*/
    BOOL bSupportMulticast;
  }

  于是服务端可以发送多播数据给支持多播的客户端,发送普通的UDP数据报给那些不支持多播的客户端。然而,当服务端也不支持多播时我们只能使用以前的老方法了。这里有一个将多播作为服务端选项的代码片段:

  int SendToAll(char *Data)
  {
    if(bServerSupportMulticast)
    {
      // First send multicast, then send individually
      // to those who don't support it
      SendMulticast(Data, addrMulticast);
      for(int index = 0; index < MAX_CLIENTS; index++)
      {
        if(Clients[index].Exist && !Clients[index].bSupportMulticast)
        {
          OldSendToClient(Data, Clients[index].addrRemote);
        }
      }
    }
    else
    {
      // Use the old method all the way regardless of support
      // as we ourselves don't support it
      for(int index = 0; index < MAX_CLIENTS; index++)
      {
        if(Clients[index].Exist)
        {
          OldSendToClient(Data, Clients[index].addrRemote);
        }
      }
    }
  }

  我希望我能为多播技术在游戏中的应用贡献出一份力量。如果你对这篇文章感到有一点兴趣或发现文章中的问题,请留下你的消息,说“我希望能很快写出下一篇文章”。现在,愿你愉快地使用多播。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章