一直在尝试使用QUIC协议发送视频流,前后原因选择了rust实现的,但当整合demo测试的时候发现存在很多问题。
首先需要说明的是quic是基于UDP的,在udp的socket基础上一端发送初始的version assosiation数据,然后在两端的socket的read event回调处理完version assosiation以及retry包后创建quic连接。再通过quic连接的连接id进继而行通信。
1.C语言demo本身的UDP的socket读写事件轮训使用的是libev,ev_loop事件循环阻塞会阻塞主线程,server和client端分别根据udp的socket监听读事件,socket创建后首次的发送version assosiation数据来驱动socket的read event完成整个通信流程,一端只能在收到数据后,再进行发数据,很显然demo的实用价值不大,甚至无法根据demo使用的接口对quiche的对外接口作稍微深入点的理解。我在集成的时候因为不能阻塞主线程,所以只好单独起了个线程完成UDP的socket创建,即浪费了资源,而且需要额外管理这个线程,当时也还没考虑到线程安全。
2.虽然Rust语言本身好像通过所有权等机制可以做到线程安全,但按照cloudflare维护人员所述,quichce创建quic连接是非线程安全的,似乎创建quic连接和使用quic连接进行通信只能在同一个线程,demo中是在socket的read event中创建的,导致原本想要通过quic连接在其他线程发送数据变得困难(因为一般情况下使用时,发送数据的线程,并不一定是创建连接的线程),是否能通过保护连接临界区做到线程安全,并没有明确。以下摘自维护人员对部分问题的答复,涉及大文件数据发送和线程安全。
The quiche_conn and quiche_h3_conn types are not thread safe unfortunately, so they shouldn't be used across threads without some kind of synchronization mechanism.
该quiche_conn和quiche_h3_conn类型不是线程安全的不幸,所以他们不应该跨线程使用却不使用某种同步机制。
We don't currently have any plan, though it also wouldn't necessarily fix the issue you are seeing. In alternative to that you can probably use a mutex on the connection object or something along those lines.
我们目前没有任何计划,尽管它也不一定能解决您遇到的问题。除此之外,您还可以在连接对象上使用互斥锁,或者在这些对象上使用互斥锁。
In any case as I said above sending and receiving from different threads is not supported.
就像我在上面说的那样,无论如何都不支持从不同线程发送和接收。
上述描述摘自以下问题答复:
quiche_h3_conn_poll and quiche_h3_send_response function are thread safety?
Using demo to continuously transfer large files will stop sending
packets lost when sending data and Flushing buffer immediately
3.按照创建quic连接的线程才能收发数据,那么如何在项目中使用比较麻烦。第一连接的创建线程和数据收发线程要在同一个线程,怎么看都比较别扭,而且要保证线程安全,实际应该无法同时收发数据的。其次demo所示其实socket的read回调线程中管理quic连接本身也不合理。
4.收发线程如果不能分开,那么持续发送数据就会成为麻烦。因为发送数据阻塞接受数据,以至于发送数据后收不到回包,会引起拥塞控制判定数据阻塞,阻塞数据写入缓冲区。
5.即使通过修改拥塞控制的cwnd可以允许连续发送更多的数据,但是也仅仅是增大了拥塞判断阈值,无法解决根本问题。
6.当下在不考虑线程安全的情况下,实现的额外的写线程从server端创建双向流,想客户端发送数据,同时保留原有的read回调线程,理论上是把收发分开了,即使持续的发送数据,也不会阻塞读取ack应答,但实际测试结果依然是由于拥塞控制导致发送数据在送入缓冲区的时候被截断,默认情况下只能发3K多的数据。增大cwnd后是可以一次性持续分片10K发送30M数据,但此种应该是类似于关闭了拥塞控制功能,并非解决问题的方式。
目前也没有好解决办法。
2020.12.28
发现一个基于cloudflare的quiche实现的应用,好像比quiche给的demo强,而且似乎实现了视频流(windows抓图)的发送,待研究
https://github.com/reneeichhorn/brocky