来自地狱的网络数据竞争状况
我正在编写网络客户端/服务器(Windows XP / C#),以便在另一个开发人员编写的非常老的(Encore 32/77)工作站上使用类似的应用程序。
该应用程序所做的基本上是在主机上共享/处理某些数据,以控制我们的花式基于PC的多显示器触摸屏UI的主机进程。
它使用3层结构来做到这一点。通信过程向主机读取/写入数据,进行所有必要的格式转换(字节序,浮点格式等),并将值写入/读取数据库。该数据库充当了通讯和触摸屏用户界面之间的数据中介。触摸屏UI的应用程序根据连接到PC的监视器数量(它会自动检测到此情况)生成触摸屏界面。
在给定的时间范围内,主机和我们的PC之间一次只能发送最多128个值,每次往返最大延迟为〜110ms(UDP用于在两个主机之间进行直接x-over以太网连接计算机)。因此,严格控制基于连接的触摸屏的可变数量允许的变量数量。此外,主机(尽管具有相当复杂的多处理器体系结构,并且具有用于实时计算的共享内存总线)具有我手机的处理能力的大约1/100,因此它被要求执行尽可能少的处理,并且它是服务器/ client必须以汇编形式编写以确保这一点(主机正在运行不受我们程序影响的完整实时模拟)。
问题是。在触摸屏上更改某些值时,不仅会采用新输入的值,还会在该值和先前的值之间随机循环。这种现象只有在某些特定页面上的某些特定值与页面的某种组合下才会表现出来。在开始通过最初的客户接受流程开始运行之前,我们几乎完全错过了该问题
为了解决这个问题,我选择了一个振荡值:
- 我检查了触摸屏应用程序,它正在振荡
- 我检查了数据库,振荡了
- 我检查了通讯应用程序
然后我爆发了wireshark,开始手动解码数据包捕获。结果:
我遍历了comms代码的每个细节一百次,没有发现任何缺陷/错误。
最终,我开始向另一位开发人员发送电子邮件,详细询问他的工作如何查看我是否缺少某些东西。然后我找到了。
显然,当他发送数据时,他没有在传输之前刷新数据数组,因此,从本质上讲,他只是用新值覆盖了使用的最后一个缓冲区,而新值覆盖了旧值,但仍未被传输的旧值仍在传输。
因此,如果某个值位于数据数组的位置80,并且所请求的值列表更改为小于80,但该相同值包含在新列表中,则这两个值将在该数据缓冲区的任何位置存在于该特定缓冲区中。给定时间。
从数据库中读取的值取决于UI请求该值的时间片。
解决方法非常简单。读入数据缓冲区中传入的项目数(实际上已包含在数据包协议中),不要读取超出该项目数的缓冲区。
得到教训:
不要将现代计算能力视为理所当然。曾经有一段时间,计算机不支持以太网,而冲洗阵列可能被认为是昂贵的。如果您真的想看看我们走了多远,请想象一个几乎没有任何形式的动态内存分配的系统。IE,执行过程必须按顺序为所有程序预分配所有内存,并且没有程序可以超出该范围。IE,在不重新编译整个系统的情况下为程序分配更多的内存可能会导致严重的崩溃。我想知道是否有人会以同样的方式谈论垃圾收集的日子。
使用自定义协议进行联网(或通常处理二进制数据表示形式)时,请确保您已阅读规范,直到了解通过管道发送的每个值的每个功能。我的意思是,请阅读直到您的眼睛受伤为止。人们通过操纵单个位或字节来处理数据,它们具有非常聪明和有效的处理方式。缺少最细微的细节可能会破坏系统。
修复的总时间为2-3天,其中大部分时间花在其他事情上,这让我感到沮丧。
注意:默认情况下,所讨论的主机不支持以太网。驱动它的卡是定制和改装的,实际上协议栈根本不存在。与我一起工作的开发人员是程序员的地狱,他不仅在该项目的系统上实现了UDP的精简版和最少的假以太网堆栈(处理器的功能不足以处理完整的以太网堆栈)但是他不到一周就做到了。他还是最初设计和编程操作系统的原始项目团队负责人之一。可以这么说,无论他经历了多久或有多少新知识,他必须分享的有关计算机/编程/体系结构的所有内容,我都会听每个单词。