代码之家  ›  专栏  ›  技术社区  ›  cfeduke

将Int32转换为ushort并再次转换

  •  1
  • cfeduke  · 技术社区  · 16 年前

    我正试图设计一个系统,将大于65535的整数值打包到一个ushort中。让我解释一下。

    1. 由于未过期,某些小于65535的ID可能随时仍在给定客户端上使用。
    2. 我们不能有任何ID冲突-也就是说,如果包ID 1转到客户端,那么当应用于65536时,跟踪从Int32中删除65535以生成ushort的次数的算法也会导致1,从而导致冲突。
    3. 我们必须能够在返回时将ushort重建为Int32。

    我们讨论了三种不同的翻译程序:

    1. 乘法:在字节字段中存储我们从Int32中删除65535以生成ushort的次数。这有上面详述的碰撞问题。
    2. 序列化会话状态:对于每个客户端,根据有关该客户端的事实生成会话ID。然后存储一个1:1的转换表,从1开始,直到交付的包数,这样当客户端再次访问我们的服务器时,包的清单可以转换回它们已知的数据库ID。这会带来开销问题,因为我们会将序列化会话状态备份到数据库,并且我们希望每秒支持数百到数千个事务。
    3. 不同的算法方法,其中字节字段是转换算法的ID,该转换算法接受Int32并将其转换为ushort。显然,其中许多将是简单的乘法(为了增加我们可以转换的ID上限),但有些将必须是较小边界的乘法(如32768),加上/减去一个数字,以获得尽可能接近可以保证在兄弟姐妹中唯一的数字。这种方法是处理器密集型的,但应该允许我们在保持可伸缩性的同时避免冲突(尽管通过这种方法,我们有一个有限的上限,在ushort问题因升级而自行消失之前无法达到)。

    澄清:这并不是说ushort上限是最大的问题,而是客户端API使用了ushort,因此我无法在客户端上组合字节字段以获得更大的值(客户端API是不可升级的,但最终将逐渐消失)。

    3 回复  |  直到 16 年前
        1
  •  1
  •   Mecki    16 年前

    第二种方法是NAT的工作原理。本地网络上的每个TCP/UDP客户端最多使用65535个端口(端口0除外)和一个专用IP。路由器只知道一个公共IP。由于两个客户端可能都有源端口300,它不能简单地用公共IP替换私有IP,这将导致出现冲突。因此,它取代了IP并“转换”端口(NAT:网络地址) 翻译

    我不太清楚的是你曾经说过

    20个左右的例子 这些ID-让我们称它们为包- 在任何给定的时间,它只需要 让他们在当地人中独树一帜

    但是你说

    某些小于65535的ID可能仍然有效 在给定客户机上的任何时间

    我想,您可能认为第二条语句的意思是,如果客户机请求ID 65536,它的ID可能仍然低于65535,而这些ID可能低至(比方说)20。客户机并不是以直接的顺序处理ID,对吗?所以你不能说,仅仅因为它现在请求65536,它可能有一些较小的值,但肯定不在1-1000范围内,对吗?它可能实际上保留了对20、90、2005和41238的引用,但仍然超过65535,这就是你的意思?

    任何可能的数字(它将进行大跳跃)。如果在32位上应用一个神奇的转换函数,从中生成16位(+一个额外的字节),然后再将其转换回来是如此简单,那么我猜世界上的每种压缩方法都会使用它,因为它可以,无论32位的数字是什么,总是将其压缩到24位(16位+一个字节)。那会很神奇。不可能将32位打包成24位,也不可能将所有逻辑打包成如何将其转换回24位。您将需要一些外部存储,这使我们回到您的第二种方法。这是唯一有效的方法,它适用于32位数字范围内的每个数字。

        2
  •  1
  •   mancaus    16 年前

    我可以想出几个其他的选择:

    索引中的大多数条目是否少于,比如50000?如果是这种情况,您可以直接映射这些值,并为其余的值使用与会话关联的映射。

    如果持久化这样的会话数据是一个问题,并且客户端的数量相当少,那么可以启用客户端/会话关联并维护服务器本地的映射。

    如果它不是web应用程序,则可以在客户机上维护地图。

        3
  •  0
  •   ctacke    16 年前

    你需要比65535多多少?您总是可以从“字节字段”中添加一些位作为ID的高阶位。仅2位将使您达到262143,3位将使您达到524287。