设为主页 | 加入收藏 | 繁體中文

网络游戏通讯模型初探①


  ...
  接收到某玩家的移动输入或NPC的移动逻辑输入;
  // 此处只以移动为例
  进行此玩家/NPC在舆图场景能否可移动的逻辑判断;
  if( 可移动 )
  {
  对此玩家/NPC进行服务器移动处理;
  发送移动消息给客户机;
  发送此玩家的移动消息给场景上全部玩家;
  }
  else
  发送不行移动消息给客户机;
  }
  Exit()  // 游戏服务=器竣事
  {
  接收到玩家离开消息;
  将此消息发送给场景中全部玩家;
  发送容许离开的信息;
  将玩派别据存入数据库;
  刊出此玩家在服务器内存中的数据;
  }
  }
  让我们来阐明一下上面简略网络游戏模子的运行机制。先来讲讲服务器端,这里服务器端分为三个部门(实际上一个完备的网络游戏远不止这些):登入模块、游戏模块和登出模块。登入模块用于监听网络游戏客户端发送过来的网络连接消息,而且验证其正当性,然后在服务器中创建这个玩家而且把玩家领导到游戏模块中; 游戏模块则提供给玩家用户实际的应用服务,我们在背面会细致先容这个部门; 在失掉玩家要离开游戏的消息后,登出模块则会把玩家从服务器中删除,而且把玩家的属性数据保存到服务器数据库中,如: 履历值、品级、生命值等。
  接上去让我们看看网络游戏的客户端。这时候,客户端不再像单机游戏一样,初始化数据后直接进入游戏,而是在与服务器创建连接,而且失掉容许的前提下才进入游戏。除此之外,网络游戏的客户端游戏历程需要不停与服务器进行通讯,通过与服务器互换数据来确定以后游戏的形态,例如其他玩家的位置变化、物品失落环境。异样,在离开游戏时,客户端会向服务器见告此玩家用户离开,以便于服务器做出相应处理。
  以上用简略的伪代码给大家阐述了单机游戏与网络游戏的执行流程,大家应该可以明白看出两者的差别,以及两者间相互的关系。我们可以换个角度考虑,网络游戏就是把单机游戏的逻辑运算部门搬移到游戏服务器中进行处理,然后把处理效果(包罗其他玩派别据)通过游戏服务器返回给连接的玩家。
  网络互连
  在了解了网络游戏根本形态之后,让我们进入真正的实际应用部门。首先,作为网络游戏,除了常规的单机游戏所必需的工具之外,我们还需要增长一个网络通讯模块,固然,这也是网络游戏较为重要的部门,我们来讨论一下如何实现网络的通讯模块。
  一个完善的网络通讯模块触及面相当广,本文仅对较为根本的处理方式进行讨论。网络游戏是由客户端和服务器构成,相应也需要两种不同的网络通讯处理方式,不外也有相同之处,我们先就它们的配合点来进行先容。我们这里以Microsoft Windows 2000 [2000 Server]作为开发平台,而且使用Winsock作为网络接口(大概一些朋侪会考虑使用DirectPlay来进行网络通讯,不外对于以后在线游戏,DirectPlay并不得当,具体原因这里就不做讨论了)。
  确定好平台与接口后,我们开始进行网络连接创建之前的一些须要的初始化工作,这部门无论是客户端大概服务器都需要进行。让我们看看上面的代码片段:
  WORD wVersionRequested;
  WSADATAwsaData;
  wVersionRequested MAKEWORD(1, 1);
  if( WSAStartup( wVersionRequested, &wsaData ) !0 )
  {
  Failed( WinSock Version Error!" );
  }
  上面通过调用Windows的socket API函数来初始化网络设备,接上去进行网络Socket的创建,代码片段如下:
  SOCKET sSocket socket( AF_INET, m_lProtocol, 0 );
  if( sSocket == INVALID_SOCKET )
  {
  Failed( "WinSocket Create Error!" );
  }
  这里需要阐明,客户端和服务端所需要的Socket连接数目是不同的,客户端只需要一个Socket连接足以餍足游戏的需要,而服务端必需为每个玩家用户创建一个用于通讯的Socket连接。固然,并不是说要是服务器上没有玩家那就不需要创建Socket连接,服务器端在启动之时会天生一个特殊的Socket用来对玩家创建与服务器连接的请求进行相应,等先容网络监听部门后会有更细致阐明。
  有初始化与创建一定就有释放与删除,让我们看看上面的释放部门:
  if( sSocket != INVALID_SOCKET )
  {
  closesocket( sSocket );
  }
  if( WSACleanup() != 0 )
  {
  Warning( "Can't release Winsocket" );
  }
  这里两个步骤分别对前面所作的创建初始化进行了相应释放。
  接上去看看服务器端的一个网络执行处理,这里我们假定服务器端已经创建好一个Socket供使用,我们要做的就是让这个Socket酿成监听网络连接请求的专用接口,看看上面代码片段:
  SOCKADDR_IN addr;
  memset( &addr, 0, sizeof(addr) );
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl( INADDR_ANY );
  addr.sin_port = htons( Port );  // Port为要监听的端口号
  // 绑定socket
  if( bind( sSocket, (SOCKADDR*)&addr, sizeof(addr) ) == SOCKET_ERROR )
  {
  Failed( "WinSocket Bind Error!");
  }
  // 进行监听
  if( listen( sSocket, SOMAXCONN ) == SOCKET_ERROR )
  {
  Failed( "WinSocket Listen Error!");
  }
  这里使用的是阻塞式通讯处理,此时步伐将处于等待玩家用户连接的形态,假使这时候有客户端连接出去,则通过accept()来创建针对此玩家用户的Socket连接,代码片段如下:
  sockaddraddrServer;
  int nLen sizeof( addrServer );
  SOCKET sPlayerSocket accept( sSocket, &addrServer, &nLen );
  if( sPlayerSocket == INVALID_SOCKET )
  {
  Failed( WinSocket Accept Error!");
  }
  这里我们创建了sPlayerSocket连接,今后游戏服务器与这个玩家用户的通讯全部通过此Socket进行,到这里为止,我们服务器已经有了担当玩家用户连接的功能,如今让我们来看看游戏客户端是如何连接到游戏服务器上,代码片段如下:
  SOCKADDR_IN addr;
  memset( &addr, 0, sizeof(addr) );
  addr.sin_family = AF_INET;// 要连接的游戏服务器端口号
  addr.sin_addr.s_addr = inet_addr( IP );// 要连接的游戏服务器IP地址,
  addr.sin_port = htons( Port );//到此,客户端和服务器已经有了通讯的桥梁,
  //接上去就是进行数据的发送和接收:
  connect( sSocket, (SOCKADDR*)&addr, sizeof(addr) );
  if( send( sSocket, pBuffer, lLength, 0 ) == SOCKET_ERROR )
  {
  Failed( "WinSocket Send Error!");
  }
  这里的pBuffer为要发送的数据缓冲指针,lLength为需要发送的数据长度,通过这支Socket API函数,我们无论在客户端大概服务端都可以进行数据的发送工作,同时,我们可以通过recv()这支Socket API函数来进行数据接收:
  if( recv( sSocket, pBuffer, lLength, 0 ) == SOCKET_ERROR )
  {
  Failed( "WinSocket Recv Error!");
  }
  此中pBuffer用来存储获取的网络数据缓冲,lLength则为需要获取的数据长度。
  如今,我们已经了解了一些网络互连的根本知识,但作为网络游戏,如此简略的连接方式是无法餍足网络游戏中百人千人同时在线的,我们需要更合理容错性更强的网络通讯处理方式,固然,我们需要先了解一下网络游戏对网络通讯的需求是怎样的。
 


    文章作者: 福州军威计算机技术有限公司
    军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。

TAG:
评论加载中...
内容:
评论者: 验证码: