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

电商网站建设与运营专业营销企业

电商网站建设与运营专业,营销企业,fedora做网站服务器,河南做网站企起一、项目创立初衷: 由于之前学过计算机网络的相关知识,了解了计算机网络的基本工作原理,对于主流的协议有一定的了解。但对于应用层的协议还知之甚少,因此我去了解了下目前主要的应用层传输协议,发现RTSP(…

一、项目创立初衷:

由于之前学过计算机网络的相关知识,了解了计算机网络的基本工作原理,对于主流的协议有一定的了解。但对于应用层的协议还知之甚少,因此我去了解了下目前主要的应用层传输协议,发现RTSP(实时传输协议)在实时传输方面有很大的贡献,于是我开始了对于该协议的学习、研究,并创建了该项目。
 

二、总体设计:

 服务器处理流程简述:

        创建tcp连接套接字;绑定地址;监听;

        再建立通信套接字,接收客户端连接-->处理客户端请求-->处理完毕,释放资源、关闭套接字。

三、细部设计

1.rtp数据包的设计及相关函数:

要想发送rtp数据包,首先要定义rtp包结构体(在rtp.h文件中设置):

rtp首部字段:

struct RtpHeader
{//rtp协议头部/* byte 0 */uint8_t csrcLen : 4;//CSRC计数器,占4位,指示CSRC 标识符的个数。uint8_t extension : 1;//占1位,如果X=1,则在RTP报头后跟有一个扩展报头。uint8_t padding : 1;//填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。uint8_t version : 2;//RTP协议的版本号,占2位,当前协议版本号为2。/* byte 1 */uint8_t payloadType : 7;//有效载荷类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等。uint8_t marker : 1;//标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。/* bytes 2,3 */uint16_t seq;//占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。接收者通过序列号来检测报文丢失情况,重新排序报文,恢复数据。/* bytes 4-7 */uint32_t timestamp;//占32位,时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。/* bytes 8-11 */uint32_t ssrc;//占32位,用于标识同步信源。该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的SSRC。/*标准的RTP Header 还可能存在 0-15个特约信源(CSRC)标识符每个CSRC标识符占32位,可以有0~15个。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源*/
};

rtp包结构体:

struct RtpPacket
{   //头部字段struct RtpHeader rtpheader;//信息载体uint8_t payload [0];
};

定义初始化rtp包的函数、通过udp发送rtp数据包的函数(rtp.cpp文件中):

//初始化数据包

void rtpHeaderInit(struct RtpPacket* rtpPacket, uint8_t csrcLen, uint8_t extension,
    uint8_t padding, uint8_t version, uint8_t payloadType, uint8_t marker,
    uint16_t seq, uint32_t timestamp, uint32_t ssrc)

//通过udp发送

int rtpSendPacketOverUdp(int serverRtpSockfd, const char* ip, int16_t port, struct RtpPacket* rtpPacket, uint32_t dataSize)

2.处理客户端流程:

1.根据创建的通信套接字,接收客户端发送的数据(rtsp数据包的负载),存储到接收缓冲区

2.通过接收的数据,判断客户端的请求类型:

由于连接时,双方发送的rtsp信息以 \r\n结尾:

eg:

所以可以用strtok函数,将接收的数据分行存储,并逐次判断:

const char* sep = "\n";//1.分解接受缓冲区中数据,根据不同类型做出相应
char* line = strtok(rBuf, sep);     //以sep分割字符串rBuf,并存储在line中

再以用strstr函数,判断是哪种请求(RTSP的请求:OPTIONS、DESCRIBE、SETUP、PLAY、TERADOWN),若不是请求字段,则根据其数据格式,考察其他字段。

strstr(line,"OPTIONOS");

eg:

根据接收的消息,找到关于客户端的相关信息,为数据包的发送做准备。 

   //考察CSeq字段else if (strstr(line, "CSeq")) {if (sscanf(line, "CSeq: %d\r\n", &CSeq) != 1) {     //将服务器收到的CSeq赋值给C传入的CSeq参数// error}}//考察Transport字段,else if (!strncmp(line, "Transport:", strlen("Transport:"))) {// Transport: RTP/AVP/UDP;unicast;client_port=13358-13359// Transport: RTP/AVP;unicast;client_port=13358-13359if (sscanf(line, "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n",&clientRtpPort, &clientRtcpPort) != 2) {    //从请求消息中获取客户端 ip、port// errorprintf("parse Transport error \n");}}line = strtok(NULL, sep);   //将line(客户端发送的数据)进行到下一行}

3.根据其请求的类型,做出相应的处理:

static int handleCmd_OPTIONS(char* result, int cseq)
{sprintf(result, "RTSP/1.0 200 OK\r\n""CSeq: %d\r\n""Public: OPTIONS, DESCRIBE, SETUP, PLAY\r\n""\r\n",cseq);return 0;
}static int handleCmd_DESCRIBE(char* result, int cseq, char* url)
{char sdp[500];char localIp[100];sscanf(url,"rtsp://%[^:]:", localIp);sprintf(sdp, "v=0\r\n""o=- 9%ld 1 IN IP4 %s\r\n""t=0 0\r\n""a=control:*\r\n""m=video 0 RTP/AVP 96\r\n""a=rtpmap:96 H264/90000\r\n""a=control:track0\r\n",time(NULL), localIp);sprintf(result, "RTSP/1.0 200 OK\r\nCSeq: %d\r\n""Content-Base: %s\r\n""Content-type: application/sdp\r\n""Content-length: %zu\r\n\r\n""%s",cseq,url,strlen(sdp),sdp);return 0;
}//传入序号、Rtp端口参数,作为SETUP请求的回应
static int handleCmd_SETUP(char* result, int cseq, int clientRtpPort)
{sprintf(result, "RTSP/1.0 200 OK\r\n""CSeq: %d\r\n""Transport: RTP/AVP;unicast;client_port=%d-%d;server_port=%d-%d\r\n""Session: 66334873\r\n""\r\n",cseq,clientRtpPort,clientRtpPort + 1,SERVER_RTP_PORT,SERVER_RTCP_PORT);return 0;
}static int handleCmd_PLAY(char* result, int cseq)
{sprintf(result, "RTSP/1.0 200 OK\r\n""CSeq: %d\r\n""Range: npt=0.000-\r\n""Session: 66334873; timeout=10\r\n\r\n",cseq);return 0;
}static int handleTEARDOWN(char *result,int cseq)
{                               sprintf(result,"RTSP/1.0 200 OK\r\n""CSeq: %d \r\n",cseq);return 0;
}

若为setup请求,需要开始建立连接,创建rtp、rtcp udp套接字,绑定地址,最后在传输阶段(PLAY),通过这两个套接字,以及接收到的客户端的端口,发送数据

4.在发送数据前,要先从本地的h264文件读取数据:

由于h264文件是由一个个NALU构成的,且每个NALU之间有固定的间隔符(00 00 00 01或 00 00 01),

static int getFrameFromH264File(FILE* fp, char* frame, int size) {int rSize, frameSize;char* nextStartCode;if (fp < 0)return -1;rSize = fread(frame, 1, size, fp);//每次读取的长度//h264由一个个NALU构成,每个NALU以 0001 0010隔开//根据分隔符0001 0010每次读取一个NALUif (!startCode3(frame) && !startCode4(frame))return -1;//找到第一个开始的编码nextStartCode = findNextStartCode(frame + 3, rSize - 3);    //减去分隔符,数据指针后移if (!nextStartCode){//lseek(fd, 0, SEEK_SET);//frameSize = rSize;return -1;}else{//寻找成功frameSize = (nextStartCode - frame);//退回到fseek(fp, frameSize - rSize, SEEK_CUR);}return frameSize;
}

5.通过UDP协议发送数据

1.通过framesize大小判断该包应该是何种打包模式

 单一NALU单元打包模式:(framesize<rtp的最大限制)

 memcpy(rtpPacket->payload, frame, frameSize);ret = rtpSendPacketOverUdp(serverRtpSockfd, ip, port, rtpPacket, frameSize);if (ret < 0)return -1;rtpPacket->rtpHeader.seq++;sendBytes += ret;   if ((naluType & 0x1F) == 7 || (naluType & 0x1F) == 8) // 如果是SPS、PPS(只是编解码需要的数据,并非视频数据)就不需要加时间戳goto out;

分包模式:(framesize<rtp的最大限制)

nt remainPktSize = frameSize % RTP_MAX_PKT_SIZE; // 剩余不完整包的大小int i, pos = 1;// 发送完整的包for (i = 0; i < pktNum; i++){//根据NALU包格式解析rtpPacket->payload[0] = (naluType & 0x60) | 28;rtpPacket->payload[1] = naluType & 0x1F;if (i == 0) //第一包数据rtpPacket->payload[1] |= 0x80; // startelse if (remainPktSize == 0 && i == pktNum - 1) //最后一包数据rtpPacket->payload[1] |= 0x40; // end//从负载的第三个数据包开始拷贝memcpy(rtpPacket->payload + 2, frame + pos, RTP_MAX_PKT_SIZE);ret = rtpSendPacketOverUdp(serverRtpSockfd, ip, port, rtpPacket, RTP_MAX_PKT_SIZE + 2);if (ret < 0)return -1;rtpPacket->rtpHeader.seq++;sendBytes += ret;pos += RTP_MAX_PKT_SIZE;}// 发送剩余的数据if (remainPktSize > 0){rtpPacket->payload[0] = (naluType & 0x60) | 28;rtpPacket->payload[1] = naluType & 0x1F;rtpPacket->payload[1] |= 0x40; //endmemcpy(rtpPacket->payload + 2, frame + pos, remainPktSize + 2);ret = rtpSendPacketOverUdp(serverRtpSockfd, ip, port, rtpPacket, remainPktSize + 2);if (ret < 0)return -1;rtpPacket->rtpHeader.seq++;     //发送完毕之后进行序号的累加sendBytes += ret;}}

四、效果实现

meeting_01

http://www.shuangfujiaoyu.com/news/63235.html

相关文章:

  • 建立个人网站的方法网页设计制作网站模板图片
  • 三网合一网站系统在哪里可以发布自己的广告
  • 山西省新农村建设网站合肥百度快速排名优化
  • 付运费送东西的网站怎么做6网站怎么添加外链
  • 做视频网站需要什么资质seo代做
  • vue 企业网站模板网页查询
  • 做外贸在哪个网站好企业网络推广的方式有哪些
  • https网站怎么做百度推广怎么操作
  • 阿里云oss做网站seo关键词外包
  • 嘉兴专业定制网站制作企业爱网站关键词挖掘工具
  • 网站文章图片加标签加搜索引擎优化常用方法
  • 创建建站百度seo关键词优化方案
  • 郑州做商城网站公司棋牌软件制作开发多少钱
  • 用mediawiki做的网站企业网站推广优化
  • 网站群建设公司站长统计幸福宝下载
  • 做影视网站存储视频会侵权吗seo是什么专业
  • 在长沙做网站微信软文范例100字
  • 怎么学做网站优化网站排名工具
  • 德州 网站建设北京疫情消息1小时前
  • 国产做网站营销活动
  • app使用什么做的网站郑州好的seo外包公司
  • 东莞做营销型网站google应用商店
  • 网络服务大厅山东理工大学厦门seo厦门起梦
  • 微九州合作网站百度经验悬赏令
  • 津云天津最新疫情无线网络优化工程师
  • 网站建设seo优化推广聚名网域名注册
  • 杭州网站搭建公司湖南省人民政府官网
  • 兼职网站高中生在家可做病毒什么时候才能消失
  • 金融网站建设方案google seo优化
  • 什么网站可以做高三英语试题无锡百度竞价