c语言socket编程备忘

近期有个小项目,要把手机上的视频上传到云端,云端再提供webui给用户在线查看

手机上的视频来源不是摄像头,而是与手机相连的嵌入式设备的摄像头

因为嵌入式设备的主板是现成并且闭源的,无法修改,对外提供了一个server地址端口,需要破解其交互信令才能成功捕获视频流,好在有java和python的客户端可以参考,所以破解起来并不是很费功夫,唯一的困难是嵌入式设备仅允许热点的方式连接,没有usb,没有网口。这样,就需要一台设备,可以连接一个局域网热点(嵌入式设备,无internet),又可以访问公网(上传视频),而且要能大范围移动(半径几公里),CPU能处理720p视频,还要是开源系统,有一定的定制能力。这几点加起来,合适的只有树莓派了。

但是,看到近期因为芯片涨价导致树莓派的价格也是节节飞涨,而且我这也不是商用项目,成本也是要考量的一点,最后我选择了Android手机,因为上述条件都满足,并且没有屏幕的Android手机价格足够便宜,开发环境足够友好,而且手机自带电池,不用占用嵌入式设备的电源。

具体选择细节就不展开了,目前的任务就是在Android上编写一个java socket client,负责上传数据,在服务器ubuntu上写一个c语言的server socket,负责接收视频数据。ubuntu上已经有mjpg-streamer了,webui是现成的,相应的处理视频流插件也有了,唯一缺的就是socke接收数据。

项目架构搭好后,剩下的就是填代码了,以下是一些备忘,毕竟有几年没接触这么底层的业务逻辑了,重新拾起来还是费了些时间,总结一下。

Server端:

1)起socket时有时会碰到address in use错误,原因是调试过程中server端socket异常退出,导致资源没有释放干净,系统报错,需要设置socket option重用端口号,节约开发调试时间。

2)其socket的本地地址参数,根据情况选择,如果没有特殊要求(例如限制某个网卡访问),就可以选ANY,意思是不绑定具体网卡,好处是调试过程可以在局域网下进行,完成后再切换到公网

3)socket避免不了考虑多线程,如果要支持多个客户端,多线程就更加必要了,linux上有pthread,接口数目不多,先看懂原理再下手写代码,网上的不少示例代码都是错的;多线程的参数传递要考虑局部变量指针失效的问题,万一指向野指针,排错就比较困难;如果涉及线程间数据共享,要考虑并发的问题,或者干脆从架构上,避免并发读写,例如牺牲一些性能,换取数据读写的时间。

4)

Client端:

1)Client端负责发送数据,TCP都会涉及拆包合并的问题,如果发送的是视频流,那么就要在视频流frame之间加标签,能让接收者把数据包合并起来,涉及一个简单高效的frame数据封包协议是很有必要的,再加上一定的保留字段,为后续功能预留接口,避免服务器升级后,所有客户端都要升级的麻烦事

2)同上,涉及发送接收数据,就要考虑缓冲区大小,这个完全要根据数据包的大小来定,TCP窗口也就1k,视频帧不可能小于这个数,那么拆包大小略小于这个TCP窗口最好,但这样就增大了接收者拼包的压力;另外,缓冲区也不是越大越好,毕竟多线程的栈也是有空间大小限制的。所以高级点的做法是看接收者处理视频帧的时长,确保一个视频帧传输+拼包的时长小于视频帧处理时长即可

3)字节序的问题,涉及跨设备的数据传输,这个也是必须要考虑,所幸,这个项目并没有遇到,java的byte数组和C语言的char数组,完全是匹配的;唯一的是封包、解包函数是两种语言实现的,有的基本库函数都没有,要写两个语言版本的字符处理函数。

4)client端涉及从嵌入式设备获取视频流,这是一个socket; 再把视频流发给云端,这也是一个socket;这两个socket分别对应wifi网络和蜂窝网络;那么就涉及到两个socket绑定不同网卡的问题。Android上面当连接上WIFI网络后,蜂窝网络就自动关闭了(wifi优先,省流量的原因),在比较高的Android版本(6.0之后),Android提供了一种方法可以再wifi连接的同时再request蜂窝网络,实现双连接,然后分别绑定两个socket,公网服务器是通过域名访问的,所以对应的DNS查询也要切换到蜂窝上。这时client端其实就实现了某种软路由,把指定的数据从一个网卡搬到了另一个网卡。这也是项目最大的难点,疫情期间,费了两个周末,终于搞定。

可能会说,既然是路由,想办法在手机上配置路由表,实现数据转发不就行了。其实不行,原因是这个项目的移动性,要求手机是移动的,IP地址可能会变,传输不稳定。

项目架构图:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值