我正在制作一个简单的在线游戏,并且我遇到了不同步问题。该服务器是使用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上的实体时,您必须保留每个客户的每个实体的本地副本,否则不可能在不同的三角洲时间传输。
另一个设计可能是我们的服务器只是同步客户端,因此每个客户端都可以自己计算场景,然后将其状态发送到服务器。然后,服务器将其分配给其他客户,客户决定如何处理此信息。
任何其他设计都会导致重大问题,我很遗憾不使用任何其他设计。
如果您还有其他问题可以随时与我联系。