当前位置: 首页 > news >正文

C语言:创建简单的流媒体服务器来播放.flv文件

编写  httpFlv_server.cpp  如下

#include <iostream>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")char* get_filename(char* path) {char* last_slash = strrchr(path, '/');// 对于Windows系统,应该是 '\'if (last_slash == NULL) {last_slash = strrchr(path, '\\');}if (last_slash == NULL) {return path;} else {return last_slash + 1;}
}int main(int argc, char *argv[])
{int port = 8080;char* path;if (argc ==2){path = argv[1];} else if (argc ==3){port = atoi(argv[1]);path = argv[2];} else {printf(" usage: httpFlv_server port /your/video.flv ");return 1;}if (port <6000 || port >65500){printf(" 6000 <= port <= 65500 ");return 2;}printf("%s\n", path);int n = strlen(path);if (n >80){printf(" file path is too long.");return 3;}if (n < 8){printf(" file path is too short.");return 3;}char* ext = &path[n-4];if (strcmp(ext, ".flv") !=0){printf(" file ext is not .flv ");return 3;}printf("httpFlv_server http://127.0.0.1:%d/%s\n", port, get_filename(path));WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){perror("WSAStartup error");return -1;}SOCKET serverFd;SOCKADDR_IN server_addr;server_addr.sin_family = AF_INET;server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//server_addr.sin_addr.s_addr = inet_addr("192.168.2.61");server_addr.sin_port = htons(port);serverFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (bind(serverFd, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {perror("socket bind error");return -1;}if (listen(serverFd, SOMAXCONN) < 0) {perror("socket listen error");return -1;}constexpr char http_headers[] = \"HTTP/1.1 200 OK\r\n" \"Access-Control-Allow-Origin: * \r\n" \"Content-Type: video/x-flv\r\n" \"Content-Length: -1\r\n" \"Connection: Keep-Alive\r\n" \"Expires: -1\r\n" \"Pragma: no-cache\r\n" \"\r\n";int http_headers_len = strlen(http_headers);/*constexpr char http_headers[] = \
"HTTP/1.1 200 OK\r\n" \
"Access-Control-Allow-Origin: * \r\n" \
"Cache-Control: no-cache\r\n" \
"Content-Type: video/x-flv\r\n" \
"Connection: close\r\n" \
"Expires: -1\r\n" \       //设置资源的有效期来控制http的缓存
"Pragma: no-cache\r\n" \  //用于客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源
"\r\n"
;*/while (true){printf(" waiting ...");int len = sizeof(SOCKADDR);SOCKADDR_IN accept_addr;int clientFd = accept(serverFd, (SOCKADDR*)&accept_addr, &len);//const char* clientIp = inet_ntoa(accept_addr.sin_addr);if (clientFd == SOCKET_ERROR) {perror("accept connection error");break;}printf(" connect ... clientFd=%d\n", clientFd);unsigned char buf[4096];char bufRecv[2001] = { 0 };FILE* fp;fp = fopen(path, "rb");if (!fp) {printf("Error: fopen %s failed!", path);break;}else {int times = 0;while (true) {times++;if (times == 1) {int bufRecvSize = recv(clientFd, bufRecv, 2000, 0);printf("bufRecvSize=%d, bufRecv=%s\n", bufRecvSize, bufRecv);send(clientFd, http_headers, http_headers_len, 0);}else {//usleep(1000 * 100);Sleep(10);int bufLen = fread(buf, 1, sizeof(buf), fp);//  fseek(srcFile, 0, SEEK_CUR);int ret = send(clientFd, (char*)buf, bufLen, 0);if (ret <= 0) {break;}else {//printf("send bufLen=%d,ret=%d \n", bufLen, ret);}}}}if (fp) {fclose(fp);}closesocket(clientFd);printf("close clientFd=%d\n", clientFd);}closesocket(serverFd);return 0;
}

编译 cl httpFlv_server.cpp  /EHsc /utf-8 

运行 httpFlv_server  /flask/videos/test.flv 

或者 编写 win_gcc.bat  如下

SET INCLUDE=D:\Strawberry\c\include
SET LIB=D:\Strawberry\c\x86_64-w64-mingw32\lib
g++  %1.cpp -o %1.exe  -lws2_32

编译执行  win_gcc.bat httpFlv_server


npm i flv.js -save ;
cd D:\nodejs\node_modules\flv.js\dist ;
copy flv.min.js flv.min.js.map to /flask/static/
编写 flvPlayer.html  如下

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8" /><title> flv.js 播放器</title><script src="/static/flv.min.js"></script>
</head>
<body><video id="video1" width="1000" height="576" controls ></video><script>if (flvjs.isSupported()) {var video1 = document.getElementById('video1');var flvplayer = flvjs.createPlayer({type: 'flv', // 媒体类型: auto, flv, mp4isLive: false, // 是否是直播流,默认 trueurl: 'http://127.0.0.1:8080/test.flv'});flvplayer.attachMediaElement(video1);flvplayer.load(); // 加载流flvplayer.play(); // 播放流}</script>
</body>
</html>
  1. 用 Chrome 浏览器访问 http://localhost:5555/flv/  可以播放,测试 Edge 不支持。

  2. 也可以用 ffplay 测试是否能播放
    ffplay -i http://127.0.0.1:8080/test.flv

相关文章:

  • 怎么排查问题
  • 数据集005:螺丝螺母目标检测数据集(含数据集下载链接)
  • GDAL读取波段数据1
  • 怎么看智慧城市的发展?
  • springboot实现多开发环境匹配置
  • react中的useEffect()的使用
  • php 设置时区
  • 这款网站测试工具,炫酷且强大!【送源码】
  • redis 主从复制薪火相传 哨兵sentinel配置以及底层原理
  • MyBatis中常见标签的使用(动态SQL)
  • Java GC问题排查的一些个人总结和问题复盘
  • 【C++题解】1133. 字符串的反码
  • 开源与闭源:AI大模型发展路径的博弈
  • Windows hook介绍与代码演示
  • Flutter 中的 ColoredBox 小部件:全面指南
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • css的样式优先级
  • ECMAScript6(0):ES6简明参考手册
  • HTML5新特性总结
  • nodejs:开发并发布一个nodejs包
  • overflow: hidden IE7无效
  • python_bomb----数据类型总结
  • Wamp集成环境 添加PHP的新版本
  • WebSocket使用
  • windows下如何用phpstorm同步测试服务器
  • 从PHP迁移至Golang - 基础篇
  • 基于 Babel 的 npm 包最小化设置
  • 记一次和乔布斯合作最难忘的经历
  • 精彩代码 vue.js
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 前端面试之闭包
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 世界上最简单的无等待算法(getAndIncrement)
  • 一道面试题引发的“血案”
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • 组复制官方翻译九、Group Replication Technical Details
  • ‌‌雅诗兰黛、‌‌兰蔻等美妆大品牌的营销策略是什么?
  • #13 yum、编译安装与sed命令的使用
  • #APPINVENTOR学习记录
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (6)设计一个TimeMap
  • (java)关于Thread的挂起和恢复
  • (libusb) usb口自动刷新
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (苍穹外卖)day03菜品管理
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (多级缓存)多级缓存
  • (二)windows配置JDK环境
  • (每日一问)设计模式:设计模式的原则与分类——如何提升代码质量?
  • (五)Python 垃圾回收机制
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .net refrector
  • .NET 指南:抽象化实现的基类
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)