TCP与UDP技术决策:解决InputShare鼠标定位不准问题
在开发InputShare的付费版本时,我遇到了一个挑战:鼠标定位不准的问题。这个问题在安卓设备上尤为明显,表现为鼠标会不时大幅度移动。我尝试了多种通信逻辑的AI优化,但问题依旧存在。InputShare是一个开源项目,旨在让电脑与安卓平板/手机共用一套键盘鼠标。最初,我采用了一种简单的逻辑,即监听鼠标事件并立即发送。这种方法虽然简单,但问题也很明显:如果鼠标回报率较高,事件发送的频率会非常高,最高可达数千赫兹。为了解决这个问题,我修改了逻辑,另起一个线程以固定间隔向发送线程中推事件,这样可以统一程序在不同鼠标回报率下的行为。尽管这个版本有所改善,但仍然不佳。后来,我决定改为使用UDP。调研了相似的开源项目,如Deskflow、Barrier等,发现它们主要使用TCP协议,因为鼠标事件需要可靠传输,以避免包丢失导致的控制不准或延迟问题。虽然UDP能提供更低的延迟,但通常仅在特定低延迟场景中使用。针对项目中鼠标移动事件通信的特点,通信频率高、带宽需求小、延迟要求高,且丢失个别包几乎无影响,我认为使用UDP更优。通过Wireshark抓包,我发现大部分时候的RTT符合应用需求,但个别延迟到达的包由于TCP的有序性,会导致接收端等待,这恰恰是我的应用所不需要的。由于项目基于scrcpy的服务端部分实现,而这个项目本身不使用UDP通信,我开始动手实践,fork了scrcpy,创建了一个UDP socket专门用于监听UHID鼠标事件。由于UDP不保证包到达的有序性,我在发送端给包带上序号,并在接收端解析和检查序号,当收到的包序号小于当前收到的最大序号时,直接无视。在demo版本中,UDP服务使用固定端口,并在绑定端口时检查是否被占用,同时实现了一个响应ping信号的功能。在客户端侧,使用ping信号检查指定端口是否存在服务,如果不存在则进行顺延,如果完全扫不到端口则回退到使用TCP通信。通过这些改进,之前提到的鼠标定位不准问题得到了解决,良好。
评论已关闭