gpt4 book ai didi

server - 桌面应用程序的客户端/服务器状态同步

转载 作者:行者123 更新时间:2023-12-02 11:48:41 25 4
gpt4 key购买 nike

我正在一个需要几个客户端之间同步的桌面应用程序上工作。基本上,一群人(假设2到10之间)都运行相同的应用程序。其中一个托管一台服务器,其他客户端连接到该服务器。托管服务器的客户端也连接到自己的服务器。

应用程序应在所有客户端之间保持同步,这意味着所有客户端在应用程序中都可以看到相同的数据。具体来说,我可以用两种不同的形式定义有问题的数据:


具有特定值的简单属性(此值必须保持同步)
属性列表(列表中的项目及其值必须保持同步)


(1)的简单示例可能是:客户端当前在列表中选择了哪个项目,以及客户端鼠标指针在应用程序窗口中的当前位置是什么。这些属性不断变化,但是这些属性的数量是恒定的并且不会增长(例如,在设计时定义)。

(2)的示例可以是聊天消息列表。这些列表将在运行时增长,无法预测会有多少个项目。

这是C#中用于状态,客户端和聊天消息的示例代码:

public class State
{
// A single value shared between all clients
public int SimpleInteger {get;set;}

// List of connected clients and their individual states
public List<Client> Clients {get;set;}

// List of chat messages
public List<ChatMessage> Messages {get;set;}
}

public class Client
{
public string ClientId {get;set;}
public string Username {get;set;}

public ClientState ClientState {get;set;}
}

public class ClientState
{
public string ClientId {get;set;}
public int SelectedIndex {get;set;}
public int MouseX {get;set;}
public int MouseY {get;set;}
}

public class ChatMessage
{
public string ClientId {get;set;}
public string Message {get;set;}
}


我已经进行了很长一段时间的研究,但是无论我想到哪种状态同步,它都无法正常工作。

当我寻找解决方案时,我只会找到游戏的解决方案,但是这些解决方案并不是很有帮助,因为我的要求是不同的:


我无法处理“丢弃的更新”,也无法预测(内插或外推)其他客户端在做什么。每个客户端都需要接收每个更新以保持同步。
另一方面,我不在乎延迟(在合理范围内)。如果我看到其他客户端的更新有大约一秒钟的延迟,那就很好。
当新客户端连接(或重新连接)时,必须转移大部分状态(例如:示例2中的聊天消息列表)。每个客户端都必须了解整个聊天记录,因此在客户端连接时必须下载该聊天记录。


我当前的解决方案可以总结如下:


服务器跟踪状态,例如真理之源。
状态包含需要同步的属性。
该状态还包含已连接用户(及其用户名等)的列表。
客户还各自保留状态的本地副本,他们可以立即采取行动。例如,他们在本地状态下连续更新鼠标位置。
每当客户端更新其本地状态时,此更新就会发送到服务器。


潜在的例外是变化太快的事物,例如鼠标的位置,我将仅定期发送这些事物。

服务器还更新公共的“真相来源”状态。
最后,服务器以新的更新状态更新所有其他客户端。


最后两个步骤是我要努力的地方。我可以想到两种同步状态的方法,一种很简单,但可能效率不高,另一种很有效,但容易出错。


服务器只是将整个状态发送给所有客户端。


服务器一从客户端收到更新,就将更新应用于该状态并广播新状态。其他每个客户端都替换其本地状态。
我认为这可能会起作用,但是由于“列表”项(例如聊天消息),状态的大小会迅速增加。在我以前的尝试中,这很快成为一个问题,并且将状态发送回去变得太慢了。

服务器将相同的更新(收到的更新)重新发送给所有其他客户端。


然后,每个客户端仅将新更新本地应用到其状态以与服务器同步。
这可能会更有效,并且仅在客户端连接时才需要发送整个状态。
但是,过去,我经常遇到客户端不再同步的不同步问题。我真的不知道是什么原因造成的,可能是消息之间发生冲突(例如服务器告诉客户端更新状态中的值,但是客户端只是更新了其本地值,该值具有优先权?)。在这种情况发生之后,一切都完全出错了,因为现在将更新应用于两个不同的状态并具有不同的结果。



我正在寻找有关如何实现此目标的一般概念的指导。我正在使用几个消息传递库来实现客户端和服务器之间的实际通信,而这并不是我认为的问题。我可以确保例如在这些库中收到每条消息(尽管我不确定顺序是否得到保证)。就像我之前说的那样,滞后不是问题,但是我必须保证服务器和其他所有客户端都接收到每个状态更新。

任何帮助将是巨大的!谢谢。

最佳答案

如您所知,这是一个复杂的问题,涉及许多活动部件。在研究这个问题的过程中,我已经在各种问答网站上读到了关于此类问题的几条评论,并指出此类事情本身就是一个项目。
免责声明:我自己还没有完成此操作,所以我不知道这样做的效果如何,但是如果您还没有这样做,也许您可​​以采纳我的建议并与他们合作。我已经在实施此项目的项目中工作,但我并不直接参与该实施。
连接
由于您尚未说明要使用哪个库进行连接,因此我假设您使用的是websockets或类似的东西。如果没有,我建议您使用websockets之类的工具。它允许客户端和服务器之间(近乎)恒定的连接,以便可以向两个方向推送数据,从而避免客户端不得不轮询和提取数据。下面的链接似乎对如何实现具有指导意义,尽管我不会尝试。因为链接消失了,所以这是它们给出的第一个示例代码,这似乎很简单。

​using System.Net.Sockets;
using System.Net;
using System;

class Server {
public static void Main() {
TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 80);

server.Start();
Console.WriteLine("Server has started on 127.0.0.1:80.{0}Waiting for a connection...", Environment.NewLine);

TcpClient client = server.AcceptTcpClient();

Console.WriteLine("A client connected.");
}
}

https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server
客户端启动
服务器与客户端之间建立稳定连接后,需要确保数据同步。当用户启动应用程序时,您可以在每个表中获取最新更改的时间戳,并将其与服务器进行比较。如果它们完全相同,则可以合理地期望表没有变化。我假设每个表都有一列,其中包含对该行的最后编辑的时间戳。
对于已更改的表,您可以让服务器根据客户端的“上次更改的时间戳记”将新行和更新后的行发送到客户端。
由于不能保证100%可以连接互联网,因此您还需要跟踪客户端连接的时间以及客户端在应用程序上的访问时间(除非应用程序在没有连接的情况下无法运行)到服务器)。还需要将此信息发送到服务器,以与未连接客户端的时间间隔内更改的数据进行比较。
时间戳匹配完成后,您需要比较行计数。如果它们匹配,则可以更合理地假设表是相同的。如果不是,则可以看到有关ID /主键匹配的信息。有多种不同的方法可以做到这一点,包括1:1匹配(最慢但最可靠),或者您可以对ID进行一些数学运算(假设为数字ID),然后尝试查看每100行中的不同之处(例如)。想法:如果在客户端和服务器上添加前100行的排序后的,自动递增的整数ID是相同的,则所有这些行都在两个服务器上都存在,但是如果不匹配,则可以尝试1:1匹配以查看缺少的内容。因为这对于大型数据库可能很漫长,所以您可能希望在另一个表中跟踪这种类型的同步,因此并不需要一直这样做。
相反,您可能希望表跟踪未发送给客户端的所有数据。这将需要确认发送的数据已正确插入到客户端DB中。这也可以在客户端上跟踪未发送到服务器的内容。当然,即使您只是跟踪键,表名和时间戳,这种事情也会很快变得麻烦。如果不定期删除旧数据,则可以快速存储数百万行。这就是为什么我建议跟踪未发送的数据,以便该表不再跟踪和删除任何已“发送”的内容。
如果您不想编写所有代码并进行管理,则可以尝试使用提供此功能的库。有各种各样的。甚至Microsoft也有,但扩展支持仅为1/1/2021。在那之后会发生什么,我什至连微软都不知道,但要花1.25年的时间才能提出另一种解决方案。

使用Sync框架创建同步提供程序
Sync Framework可用于构建应用程序,该应用程序可通过网络使用任何协议来同步来自任何数据存储的数据。我们将向您展示其工作原理,并帮助您开始构建自定义同步提供程序。

https://docs.microsoft.com/en-us/previous-versions/sql/synchronization/mt490616(v=msdn.10)
https://support.microsoft.com/en-us/lifecycle/search?alpha=Microsoft%20Sync%20Framework%202.1
正常运行时间
一旦在启动时(或启动后在后台)同步了数据,就可以简单地将数据正常发送到服务器,就像用户进行更改时一样。由于您将具有websocket类型的连接,因此服务器从其他客户端获得的任何更改都可以推送到所有其他客户端。
至于在应用程序中实时更改数据,您可能需要不断轮询本地/客户端数据库以了解时间戳更改,以便可以适当地更新UI。 C#中可能有某些功能可以为您或您找到的另一个库执行此操作。
结论
在这一点上,我没有主意。在我看来,即使很多工作,这仍然可行。希望您能利用我所拥有的,并将其作为您自己如何完成任务的想法的基础。看来您还有很多工作要做,祝您好运!
脚注
由于我是几天没有答案之后的唯一答案,因此我将假设没有其他人可以提供更好的建议。如果他们愿意,我鼓励他们自己回答,而不要抱怨我的。人们期望调整这个答案,但是在发表评论时请记住社区标准。
我之所以只回答这个问题,是因为我没有看到其他人在此站点或其他站点上这样做。它在这里和那里只是零零碎碎的部分,人们仍然无法从整体上理解它。
此问题和类似问题之前已在此网站上提出,并以“范围太广”结束。如果您和读者有同样的感觉,请对问题而不是此答案进行投票。

关于server - 桌面应用程序的客户端/服务器状态同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57311441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com