More of Detail , Network Game Architecture 让我们来说明一下上面简单网络游戏模型的运行机制。 GameServer(服务器端) 这里服务器端分为三个部分(实际上一个完整的网络游戏远不止这些):登入模块、游戏模块和登出模块。登入模块用于监听网络游戏客户端发送过来的网络连接消息,并且验证其合法性,然后在服务器中创建这个玩家并且把玩家带领到游戏模块中;游戏模块则提供给玩家用户实际的应用服务,我们在后面会详细介绍这个部分;在得到玩家要离开游戏的消息后,登出模块则会把玩家从服务器中删除,并且把玩家的属性数据保存到服务器数据库中,如:经验值、等级、生命值等。 这时候,客户端不再像单机游戏一样,初始化数据后直接进入游戏,而是在与服务器创建连接,并且获得许可的前提下才进入游戏。除此之外,网络游戏的客户端游戏进程需要不断与服务器进行通讯,通过与服务器交换数据来确定当前游戏的状态,例如其他玩家的位置变化、物品掉落情况。同样,在离开游戏时,客户端会向服务器告知此玩家用户离开,以便于服务器做出相应处理。 WORD wVersionRequested; Using 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则为需要获取的数据长度。 现在,我们已经了解了一些网络互连的基本知识,但作为网络游戏,如此简单的连接方式是无法满足网络游戏中百人千人同时在线的,我们需要更合理容错性更强的网络通讯处理方式,当然,我们需要先了解一下网络游戏对网络通讯的需求是怎样的。 |
Network Game - Network Communication Model 3
最新推荐文章于 2024-11-16 12:07:10 发布