为什么这款在线游戏过了一段时间



我正在制作一个简单的在线游戏,并且我遇到了不同步问题。该服务器是使用IOCP实施的,并且由于游戏将几乎总是在LAN举行,因此延迟相对较小。

网络连接的核心算法可以描述如下:(单个名声中有4个客户端)

  • 客户端将其操作和自上最后一帧以来的弹性时间发送到服务器,然后等到从服务器中获得响应。
  • 服务器收集所有四个客户端的消息,将它们连接在一起,然后将其发送给所有四个客户端。
  • 在接收响应时,客户会通过响应中提供的消息更新游戏。

现在,我可以看到一段时间后四场比赛失败了。可以观察到我要控制的游戏与其他三个不同(这意味着其他三个是相同的),而仅通过走动就可以解决问题。

以下是代码,如果可能有帮助:

首先,服务器。每个消息都将在单独的线程中处理。

    while(game_host[now_roomnum].Ready(now_playernum)) // wait for the last message to be taken away
    {
        Sleep(1);
    }
    game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg);
    game_host[now_roomnum].SetReady(now_playernum, true);
    game_host[now_roomnum].SetUsed(now_playernum, false);
    while(!game_host[now_roomnum].AllReady()) // wait for all clients' messages
    {
        Sleep(1);
    }
    string all_msg = game_host[now_roomnum].GetAllMessage();
    game_host[now_roomnum].SetUsed(now_playernum, true);
    while(!game_host[now_roomnum].AllUsed()) // wait for all four responses are ready to send
    {
        Sleep(1);
    }
    game_host[now_roomnum].SetReady(now_playernum, false);// ready for receiving the next message
    strcpy_s(ret.msg, all_msg.c_str());

和客户端的CGame::Update(float game_time)方法:

CMessage msg = MakeMessage(game_time);//Make a message with the actions taken in the frame(pushed into a queue) and the elasped time between the two frames
CMessage recv = p_res_manager->m_Client._SendMessage(msg);//send the message and wait for the server's response
stringstream input(recv.msg);
int i;
rest_time -= game_time;
float game_times[MAX_PLAYER+1]={0};
//analyze recv operations
for(i=1; i<=MAX_PLAYER; i++)
{
    int n;
    input>>n;
    input>>game_times[i];//analyze the number of actions n, and player[i]'s elasped game time game_times[i]
    for(int oper_i = 1; oper_i <= n; oper_i++)
    {
        int now_event;
        UINT nchar;
        input>>now_event>>nchar;
        if(now_event == int(Event::KEY_UP))
            HandleKeyUpInUpdate(i, nchar);
        else //if(now_event == int(Event::KEY_DOWN))
            HandleKeyDownInUpdate(i, nchar);
    }
}
//update player
for(i=1; i<=MAX_PLAYER; i++)
{
    player[i].Update(game_times[i]);//something like s[i] = v[i] * game_time[i]
}

非常感谢。如果必要。

,我将提供更多详细信息。

您的一般设计是错误的,这就是为什么您在某个时候获得异步的原因。服务器永远不要与客户端的FPS打交道。这只是一个可怕的设计问题。一般而言,服务器计算了客户端发送给服务器的所有内容。客户只需要求服务器周围环境的当前状态即可。这样,您在服务器端独立于fps。这意味着您可以尽快更新服务器上的场景,而客户端只需检索当前状态。

当您更新每个用户服务器fps上的实体时,您必须保留每个客户的每个实体的本地副本,否则不可能在不同的三角洲时间传输。

另一个设计可能是我们的服务器只是同步客户端,因此每个客户端都可以自己计算场景,然后将其状态发送到服务器。然后,服务器将其分配给其他客户,客户决定如何处理此信息。

任何其他设计都会导致重大问题,我很遗憾不使用任何其他设计。

如果您还有其他问题可以随时与我联系。

相关内容

最新更新