多线程开发
2023年11月23日
16:41
c 语言中 主线程传递给子线程 参数 时 地址相同
c++ 传递时不同 需要用ref , c++ 传递引用也是副本 不是同一个值 会执行拷贝函数(2次)。传递值会拷贝3次
多线程真是一个神奇的东西,
主线程为 a 开辟 线程 b 中有list 存放传送给上层的消息 并且不断由a 给list 中存放数据 b 中发送后销毁数据
现有中断消息 f 需要上报 , 此刻 f 需要根据情况修正,如果 f 直接向上传递,中断 需要将list 中相关联的消息一起销毁掉
如果 f 放入 list 中 等待发送 需要保证之前的数据也能发送成功 可是这就会和中断信号违背,要注意具体情况是要马上中断 还是中断标志。
线程中使用锁机制 要注意 死锁问题发生 锁的粒度尽量小 ,释放锁 要注意 函数 return 时 或者 循环时 要注意释放的时机
读写锁 可以多个读 但是只能一个写 写的时候不能读 读的时候不能写
互斥锁 一次只有一个锁执行 锁失败 线程睡眠 后续不可知
自旋锁 一次只有一个锁执行 锁失败 线程等待 上一个结束 马上轮到我 自旋锁比较适用于锁使用者保持锁时间比较短的情况。
正是由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡
眠是非常必要的。容易死锁 限定自旋时间或者次数
在锁的频繁释放和增加情况下要注意 变量 的使用 有可能出现内存地址相同的问题,导致在未释放数据存放list 中查找出错误信息。
多客户端连接服务器开发 目前主要是 通过多线程实现 即 每当有客户端连接 server端时开启一个线程实现连接和接收信息 然后存储 socket 到列表
发送数据时 可以通过循环查询列表 发送 这样就多个客户端连接可以实现一个线程发送 recv 是阻塞的 会等待数据
线程是在start()方法被调用后开始运行的,而不是在join()方法被调用后运行。
当你创建并启动一个线程时,你通常会调用线程对象的start()方法来开始执行线程。此时,线程会独立于主线程(即调用start()的线程)运行。一旦线程开始运行,它将一直运行,直到完成其任务或遇到异常。
join()方法用于等待线程完成执行。当你调用一个线程对象的join()方法时,调用该方法的线程(通常是主线程)将被阻塞,直到被调用的线程完成执行。这意味着,join()方法用于确保主线程等待子线程完成其任务后再继续执行。
因此,线程是在start()方法被调用后开始运行的,并在join()方法被调用之前一直运行
来自 <文心一言>
多线程传输 时 如果 占用率高的 持续的事件 可以单独开一个线程 ,不和其他事件混合,
通信 多线程 开发
每个会话者开辟一个线程 适用于少量会话
会话者合并 从功能的角度出发 每个功能开辟一个线程 ,如 发送 ,接收 ,检查在线 。 适用于大量会话 当然 其他细节 如 线程调度 资源利用 需要根据情况开发
Epoll 模式
Poll 模式
Select 模式
多线程开发
2023年11月23日
16:41
c 语言中 主线程传递给子线程 参数 时 地址相同
c++ 传递时不同 需要用ref , c++ 传递引用也是副本 不是同一个值 会执行拷贝函数(2次)。传递值会拷贝3次
多线程真是一个神奇的东西,
主线程为 a 开辟 线程 b 中有list 存放传送给上层的消息 并且不断由a 给list 中存放数据 b 中发送后销毁数据
现有中断消息 f 需要上报 , 此刻 f 需要根据情况修正,如果 f 直接向上传递,中断 需要将list 中相关联的消息一起销毁掉
如果 f 放入 list 中 等待发送 需要保证之前的数据也能发送成功 可是这就会和中断信号违背,要注意具体情况是要马上中断 还是中断标志。
线程中使用锁机制 要注意 死锁问题发生 锁的粒度尽量小 ,释放锁 要注意 函数 return 时 或者 循环时 要注意释放的时机
读写锁 可以多个读 但是只能一个写 写的时候不能读 读的时候不能写
互斥锁 一次只有一个锁执行 锁失败 线程睡眠 后续不可知
自旋锁 一次只有一个锁执行 锁失败 线程等待 上一个结束 马上轮到我 自旋锁比较适用于锁使用者保持锁时间比较短的情况。
正是由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡
眠是非常必要的。容易死锁 限定自旋时间或者次数
在锁的频繁释放和增加情况下要注意 变量 的使用 有可能出现内存地址相同的问题,导致在未释放数据存放list 中查找出错误信息。
多客户端连接服务器开发 目前主要是 通过多线程实现 即 每当有客户端连接 server端时开启一个线程实现连接和接收信息 然后存储 socket 到列表
发送数据时 可以通过循环查询列表 发送 这样就多个客户端连接可以实现一个线程发送 recv 是阻塞的 会等待数据
线程是在start()方法被调用后开始运行的,而不是在join()方法被调用后运行。
当你创建并启动一个线程时,你通常会调用线程对象的start()方法来开始执行线程。此时,线程会独立于主线程(即调用start()的线程)运行。一旦线程开始运行,它将一直运行,直到完成其任务或遇到异常。
join()方法用于等待线程完成执行。当你调用一个线程对象的join()方法时,调用该方法的线程(通常是主线程)将被阻塞,直到被调用的线程完成执行。这意味着,join()方法用于确保主线程等待子线程完成其任务后再继续执行。
因此,线程是在start()方法被调用后开始运行的,并在join()方法被调用之前一直运行
来自 <文心一言>
多线程传输 时 如果 占用率高的 持续的事件 可以单独开一个线程 ,不和其他事件混合,
通信 多线程 开发
每个会话者开辟一个线程 适用于少量会话
会话者合并 从功能的角度出发 每个功能开辟一个线程 ,如 发送 ,接收 ,检查在线 。 适用于大量会话 当然 其他细节 如 线程调度 资源利用 需要根据情况开发
Epoll 模式
Poll 模式
Select 模式
音视频开发
2023年11月23日
16:40
音频信息设置要注意 可能回合视频帧分开给 ,要防止覆盖导致 设置失败
视频帧 要注意 帧率 宽高 编码格式 时间戳
音频帧 采样率 声道 采样频率
要保证视频头 的正确性。 视频头 包含了 整个视频的解析信息 ,如音频类型 ,频率 ,采样率 ,位数 视频编码类型 ,视频分辨率 ,
如果视频没有声音 可能是因为 音频信息缺失 ,
视频定位 失败 可能是 时间磋 和帧号 问题
开发音视频如果视频有问题要通过分析流数据来判断
客户端和服务端是否一致
是否丢帧
视频开发实时预览时要做好属性检查 ,如果属性变化要重新拉流。
开发外部厂家的音视频 可能存在sdk 的不兼容 或者sdk 需要更新才支持接口
天地音视频 多采用 异步回调 。。
异步回调能够快速响应 ,结果,将持续的事件独立出来 ,采用回调来执行后续事件
Ps 流 该流包含特殊信息 需要解码 e0 是视频 c0 是音频
H264 流 就是裸流 里面不包含其他信息 区分音视频 类别
天地流 需要一个头信息 才能正确解析
音视频数据每帧时间间隔如果有差异会影响音频播放卡顿,导致音频中断
音视频帧正常是每一帧视频都有对应的一帧音频
测试项 关键点
预览 过程中改变视频参数 是否能够完成重连
回放 多画面 倍速 时间回放 文件回放 定位
下载 多路下载 时间下载 文件下载 , 下载文件大小是否一致 连续下载
上墙 回放上墙 预览上墙
丢帧 花屏 跳秒 声音
Valgraind 内存检测。
影视片开发流控管理
数据发送失败 要存入数据再次尝试发送 ,不能丢帧 数据缓存要注意 不能无限缓存数据 容易导致服务器内存奔溃
获取音视频数据 分析数据 音频帧 |视频帧 音频帧不单独发 需要和视频帧一起发送 所以会先缓存音频帧 人,然后等等待视频帧的到来。 封装天地视频格式时要注意是否将音视频信息属性完善 ,帧号时间戳 是否正确
视频定位 主要 依据视频中的时间戳 如果没有一个固定变化的时间戳 无法完成定位。
网络协议
2023年11月14日
9:11
Ipv6 ping6 xxxx
Ipv4 ping xxxx
服务器开启双栈 可以同时支持 ipv6 和ipv4的请求
网络协议是一组双方约定好的特定的的传输字符片段和机制。
环境变量 动态包 依赖
建立连接 绑定ip 端口是否开放。
tcp连接数据 线程开启必要性,连接过程实现(模拟三次握手) 心跳机制 。 异步/同步数据发送 的不同处理方式
线程共用 。 通常是通过共同处理同一个数据容器来实现 ,如 循环同一个链表数据做处理
设备断开重连机制
绑定读取回调 (巧用回调)
绑定写入回调(在大量数据传输中 将数据缓存,等待连接空闲发送数据)
提取公共函数 降低耦合 (不要省事)
数据越界 。。 包粘连 数据发送不全 strcpy 慎用。
常用调试方法 : gdb(主要) tcpdump log
c 语言 --内存管理- 非正常流程结束 释放资源要慎重。通常情况下只处理本函数开辟的空间 不要乱释放 也不要不释放。
返回指针地址 作为句柄 时 返回内存地址 可能存在地址 快速开辟和关闭导致地址相同的情况
结合上层业务,判断协议sdk 开发的什么程度
工具函数 要和业务逻辑解耦
发送信息 考虑 :解析session 之类的 需要 考虑 。是否需要 不要让发送信息逻辑 夹杂太多其他的逻辑
同步 要等待数据
异步 不等待接受数据 时 考虑如何回收消息,并处理
接受数据 : 接收数据的量 不代表读取数据的量 需要循环读取 直至 全部读取完数据。
原有功能开发 要保证原有函数参数的意义一致,
消息滞后 逻辑可通过线程完成异步。
代码逻辑可以自上而下编写 也要考虑自下而上的写法 例如 通过 type 得到最终发送数据 也可以通过最终数据向上推到type 然后 拼装数据发送
## 代码设计 整体实现 同一块业务代码适配不同类型模块 可以通过预制函数指针实现 后续各个模块通过重写函数,绑定函数指针不影响业务整体流程。
*** tcp 协议
滑动窗口机制
断开连接时 会有 close_time 收到最后的确认断开应答
和wait_time 关闭时等待发送方将完整数据发送完毕 因为tcp 的滑动窗口机制
udp 协议没有发送缓存区