系统由一台播放器(服务器)和多台接收器(客户端)构成一个wifi直连的群组,服务器是群主(GO),客户端是组员(GC)。使用Wifi直连(p2p)构造一对多的系统是很方便实现的。
系统构成请参见图:wifi_p2p_一对多数据流程

上图只画出了音频数据的流程,对于服务器与客户端的文字信息交互没有表示,这部分内容看一下代码就明白了。
为了确保服务器作为群主(GO)角色出现在群组中,服务器启动时立即主动创立群组。
客户端启动后通过搜索功能发现服务器,并与之建立连接,客户端可以有多个。
通信系统采用NIO实现非阻塞的socket通信,一来有较好性能,二来避免了多用户复杂线程处理。
NIO不同于传统的阻塞式socket通信方式,无法使用功能强大的ObjectOutputStream和ObjectInputStream,将对象以数据流方式发送或接收。
因此必须自己实现传输数据的打包和解包。
本系统传输的数据有两类,文字数据和音频数据。文字数据用于向对方发送消息,音频数据以PCM形式传送声音。
粘包拆包问题的发生是NIO数据收发缓冲机制造成的,如果数据包边界超过缓冲区边界,就会发生拆包;如果数据包边界未达到缓冲区边界、且后续数据包也已到达,就会发生粘包。
服务器输出数据打包的过程很简单,由ConnectIntentService实现,使用SocketChannel.write方法依次把包类型、包长度和数据包写入TCP网络(wifi p2p)。
客户端接收数据解包的过程稍显复杂,在ConnectRunnable中实现。
解包过程使用了两个buffer,inputBuff(输入区)和cacheBuff(缓存),inputBuff用于从socketChannel中读取数据。
由于inputBuff中得到数据包有可能是不完整的,因此需要用cacheBuff缓存数据包,cacheBuff中数据包内容全部收妥后,提交给消费者。
消费者根据包类型,将数据包解析为文字数据或音频数据。
用流程图表示比较直观,请参见图:NIO解包流程

以下对重点模块做一些简单说明。
这是一个继承了Serializable的数据类,用来表示一帧音频数据。数据产生于服务器的解码器,注入socket,经过wifi p2p,传送到客户端,它包括三个成员:
这是一个专用于Wifi直连(p2p)功能的广播接收器,服务器和客户端都要用到。这里定义了几个wifi p2p事件的相应。
这是在服务器和客户端都必须实现的wifi p2p事件相应接口。服务器和客户端的实现方法有所不同。
wifi p2p连接建立后,这个IntentService主要负责实现非阻塞的socket通信。
这里涉及三个线程:
这是MP3音频解码器所需的回调。在PlayThreadHandler中将其注入解码器。主要相应以下事件:
在本地播放音频所需playThread的Runnable实体,在其中使用Looper,循环调用PlayThreadHandler。
接收并执行来自MainViewModel的与本地音频播放有关的各种指令。
安卓体系结构组件之一,集成处理逻辑和数据。主要有以下处理:
用户界面虽然有wifi p2p建组和删组按钮,通常不需要使用,系统在初始化时已经完成wifi p2p建组。
来自MainViewModel的消息,用观察者模式处理。
为了减少if-else逻辑,对于本地音频播放器按钮采用状态模式处理,缺点是增加了不少状态类。
客户端socket线程的执行部分,用NIO机制实现信息接收和发送。这里用到两个线程:
这是来自服务器的音频数据的消费者,用AudioTrack播放音频。
该类初始化时,可以控制播放器的左右声道。
同服务器MainViewModel功能相似。
如有问题、BUG、指摘,请联系:wxson@126.com
我有以下模型用户has_many:users_contactshas_many:contacts,through::users_contactsaccepts_nested_attributes_for:contacts,allow_destroy:true联系方式has_many:users_contactshas_many:users,through::users_contactsaccepts_nested_attributes_for:users_contacts,allow_destroy:true用户联系belongs_to:usersbelongs_to:contacts
我正在尝试下载一个大文件,然后使用Ruby将该文件发布到REST端点。该文件可能非常大,即超过可以存储在内存中甚至磁盘上的临时文件中的容量。我一直在用Net::HTTP尝试这个,但我愿意接受任何其他库(rest-client等)的解决方案,只要他们做我想做的事情。这是我尝试过的:require'net/http'source_uri=URI("https://example.org/very_large_file")source_request=Net::HTTP::Get.new(source_uri)source_http=Net::HTTP.start(source_uri.ho
我在Heroku上构建了一个必须在Docker容器内运行的RoR应用程序。为此,我使用officialDockerfile.因为它在Heroku中很常见,所以我需要一些附加组件才能使这个应用程序完全运行。在生产中,变量DATABASE_URL在我的应用程序中可用。但是,如果我尝试其他一些使用环境变量(在我的例子中是Mailtrap)的加载项,变量不会在运行时复制到实例中。所以我的问题很简单:如何让docker实例在Heroku上执行时知道环境变量?您可能会问,我已经知道我们可以在docker-compose.yml中指定一个environment指令。我想避免这种情况,以便能够通过项目
目录一、ESP32简单介绍二、ESP32Wi-Fi模块介绍三、ESP32Wi-Fi编程模型四、ESP32Wi-Fi事件处理流程 五、ESP32Wi-Fi开发环境六、ESP32Wi-Fi具体代码七、ESP32Wi-Fi代码解读6.1主程序app_main7.2自定义代码wifi_init_sta()八、ESP32Wi-Fi连接验证8.1测试方法8.2服务器模拟工具sscom58.3测试代码8.4测试结果前言为了开发一款亚马逊物联网产品,开始入手ESP32模块。为了能够记录自己的学习过程,特记录如下操作过程。一、ESP32简单介绍ESP32是一套Wi-Fi(2.4GHz)和蓝牙(4.2)双模解决方
本人是音乐爱好者,从小就特别喜欢那个随着音乐跳动的方框效果,就是这个:arduino上一大把对,我忍你很久了,我就想用mpy做,全网没有,行我自己研究。果然兴趣是最好的老师,我之前有篇博客专门讲音频,有兴趣的可以回顾一下。提到可视化频谱,必然绕不开fft,大学学过这玩意,当时一心玩,老师讲的一个字都么听进去,网上教程简略扫了一下,大该就是把时域转频域的工具,我大mpy居然没有fft函数,奶奶的,先放着。音频信息如何收集?第一种傻瓜式的ADC,模拟转数字,原始粗暴,第二种,I2S库,我之前博客有讲过,数据是PCM编码。然后又去学PCM编码,一学豁然开朗,舒服,以代码为例:audio_in=I2S
似乎Capistrano曾经有anextensivefiletransferpackage.但是在3.0版本重写后好像没有了。知道是否还有其他方法可以将文件传输到服务器/从服务器传输文件吗? 最佳答案 下载:desc"downloadfoobar.txtintolocal_dir/"task:foobardodownload!"some_remote_path/foobar.txt","local_dir/"end我知道这从Cap3.2.1开始有效,因为我现在正在使用它。 关于ruby-
我正在尝试将数据从我的生产数据库传输到我的登台数据库,但没有成功。我正在关注heroku的相关文档:http://devcenter.heroku.com/articles/pgbackups#transfers这些是我运行的命令...$herokuaddons:addpgbackups--remotestaging$herokuaddons:addpgbackups--remoteproduction$herokupgbackups:capture--remoteproduction$herokupgbackups:restoreDATABASE`herokupgbackups:ur
我正在使用DataMapper,一个用于ruby的开源ORM,我很想抓挠。目前,DataMapper可以对一对多关系使用StrategicEagerLoading(SEL),但不能对发生N+1查询的多对多关系使用。我想设法让这项工作正常进行,但我找不到在哪里做。所以两部分问题:如何运行测试套件,以便它显示失败(注意,现在所有应该失败的规范都标记为待定)?在何处以及如何为一对多关系实现SEL? 最佳答案 对于第二个问题,您可以尝试深入研究代码:/lib/dm-core/associations/relationship.rb#Ea
从命令行scp实用程序的功能来看,SCP上传速度似乎在库中受到很大限制。我知道这是Ruby(1.9.2-p0),但是Net::SCP比Linux实用程序慢大约8倍(使用大文件看到...见下文)。我很好奇知道(我快速查看了代码)这是否是Ruby中套接字的方式,或者是否可以更好地多路复用Net::SCP套接字?我注意到无论我尝试哪种上传方式(串行上传、异步操作channel、使用scp对象的多个实例)我都无法在SCP上传上获得超过9兆字节/秒的传输速度。现在……让我解释一下我调查的细节:1)尝试不同的加密算法我使用了不同类型的加密,速度没有太大变化示例:我可以使用命令行scp(加密算法=a
我正在寻找一种从AmazonS3动态流式下载zip文件的方法。应用程序托管在EC2上,文件存储在S3上。需要让用户能够从一组文件中进行选择,然后将这些文件打包并下载给他们。听说过一些可能可行的Actionscript库(aszip和fzip),或者可以在Ruby或什至PHP中执行此操作。文件不需要任何压缩,zip只是用于将文件捆绑到一个下载中.... 最佳答案 我使用NginxZipModule流式传输本地文件,但可以选择从远程位置流式传输。否则,您可以将它与VFS安装的S3存储一起用作本地文件系统。支持seek-断点续传和加速下载