RTSP 服务器C语言

  • Z4_909130
    了解作者
  • 10.7KB
    文件大小
  • rar
    文件格式
  • 0
    收藏次数
  • VIP专享
    资源类型
  • 1
    下载次数
  • 2022-04-22 12:26
    上传日期
RTSP是实时流媒体传输协议,服务器和客户端之间通过RTSP协议实现握手和认证过程,通过RTP协议传输视频数据包,本资源通过C语言实现了RTSP服务器的功能。
RTSP.rar
  • rtsp.c
    30.3KB
  • rtsp.h
    2.5KB
内容介绍
#ifdef __cplusplus #if __cplusplus extern "C"{ #endif #endif /* End of #ifdef __cplusplus */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <signal.h> #include <time.h> #include <netdb.h> #include <sys/socket.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/ioctl.h> #include <fcntl.h> #include <arpa/inet.h rel='nofollow' onclick='return false;'> #include <net/if.h> #include "list.h" #include "rtsp.h" #define MAX_VENC_THREAD 4 RTSP_client g_rtspClients[MAX_RTSP_CLIENT]; pthread_mutex_t g_mutex; pthread_cond_t g_cond; pthread_mutex_t g_sendmutex; struct list_head RTPbuf_head = LIST_HEAD_INIT(RTPbuf_head); int udpfd; const char *get_stat(int err) { struct { const char *token; int code; } status[] = { {"Continue", 100}, {"OK", 200}, {"Created", 201}, {"Accepted", 202}, {"Non-Authoritative Information", 203}, {"No Content", 204}, {"Reset Content", 205}, {"Partial Content", 206}, {"Multiple Choices", 300}, {"Moved Permanently", 301}, {"Moved Temporarily", 302}, {"Bad Request", 400}, {"Unauthorized", 401}, {"Payment Required", 402}, {"Forbidden", 403}, {"Not Found", 404}, {"Method Not Allowed", 405}, {"Not Acceptable", 406}, {"Proxy Authentication Required", 407}, {"Request Time-out", 408}, {"Conflict", 409}, {"Gone", 410}, {"Length Required", 411}, {"Precondition Failed", 412}, {"Request Entity Too Large", 413}, {"Request-URI Too Large", 414}, {"Unsupported Media Type", 415}, {"Bad Extension", 420}, {"Invalid Parameter", 450}, {"Parameter Not Understood", 451}, {"Conference Not Found", 452}, {"Not Enough Bandwidth", 453}, {"Session Not Found", 454}, {"Method Not Valid In This State", 455}, {"Header Field Not Valid for Resource", 456}, {"Invalid Range", 457}, {"Parameter Is Read-Only", 458}, {"Unsupported transport", 461}, {"Internal Server Error", 500}, {"Not Implemented", 501}, {"Bad Gateway", 502}, {"Service Unavailable", 503}, {"Gateway Time-out", 504}, {"RTSP Version Not Supported", 505}, {"Option not supported", 551}, {"Extended Error:", 911}, {NULL, -1} }; int i; for (i = 0; status[i].code != err && status[i].code != -1; ++i); return status[i].token; } int send_reply(int sock, int err, int cseq) { char buf[1024] = {0}; sprintf(buf, "RTSP/1.0 %d %s\r\nCSeq: %d\r\n\r\n", err, get_stat(err), cseq); int ret = send(sock, buf, strlen(buf), 0); if(ret <= 0) { return FALSE; } else { printf(">>>>>%s\n", buf); return TRUE; } } static char const* dateHeader() { static char buf[200]; time_t tt = time(NULL); strftime(buf, sizeof buf, "Date: %a, %b %d %Y %H:%M:%S GMT\r\n", gmtime(&tt)); return buf; } static char* GetLocalIP(int sock) { struct ifreq stifreq; struct sockaddr_in *sin; char * LocalIP = malloc(20); strcpy(stifreq.ifr_name,"eth0"); if (!(ioctl (sock, SIOCGIFADDR,&stifreq))) { sin = (struct sockaddr_in *)&stifreq.ifr_addr; sin->sin_family = AF_INET; strcpy(LocalIP,inet_ntoa(sin->sin_addr)); //inet_ntop(AF_INET, &sin->sin_addr,LocalIP, 16); } printf("--------------------------------------------%s\n",LocalIP); return LocalIP; } int ParseRequestString(char const* reqStr, unsigned reqStrSize, char* resultCmdName, unsigned resultCmdNameMaxSize, char* resultURLPreSuffix, unsigned resultURLPreSuffixMaxSize, char* resultURLSuffix, unsigned resultURLSuffixMaxSize, char* resultCSeq, unsigned resultCSeqMaxSize) { // This parser is currently rather dumb; it should be made smarter ##### // Read everything up to the first space as the command name: int parseSucceeded = FALSE; unsigned i; for(i = 0; i < resultCmdNameMaxSize-1 && i < reqStrSize; ++i) { char c = reqStr[i]; // '\t'是制表符 if(c == ' ' || c == '\t') { parseSucceeded = TRUE; break; } resultCmdName[i] = c; // 通过for循环把pRecvBuf中的内容复制到resultCmdName中; } resultCmdName[i] = '\0'; // 在每个命令命令后面都添加上'\0',当做字符串; if(!parseSucceeded) return FALSE; // rtsp://192.168.1.10:554/stream_chn0.h264 RTSP/1.0 // Skip over the prefix of any "rtsp://" or "rtsp:/" URL that follows: unsigned j = i + 1; while(j < reqStrSize &&(reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; // skip over any additional white space for(j = i+1; j < reqStrSize-8; ++j) { if((reqStr[j] == 'r' || reqStr[j] == 'R')//rtsp: or RTSP/ &&(reqStr[j+1] == 't' || reqStr[j+1] == 'T') &&(reqStr[j+2] == 's' || reqStr[j+2] == 'S') &&(reqStr[j+3] == 'p' || reqStr[j+3] == 'P') && reqStr[j+4] == ':' && reqStr[j+5] == '/') { j += 6; if(reqStr[j] == '/') // rtsp:// { ++j; while(j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j; } else { // This is a "rtsp:/" URL; back up to the "/": --j; } i = j; break; } } // Look for the URL suffix(before the following "RTSP/"): parseSucceeded = FALSE; unsigned k; for(k = i+1; k < reqStrSize-5; ++k) { if(reqStr[k] == 'R' && reqStr[k+1] == 'T' && reqStr[k+2] == 'S' && reqStr[k+3] == 'P' && reqStr[k+4] == '/') { while(--k >= i && reqStr[k] == ' ') {} // go back over all spaces before "RTSP/" unsigned k1 = k; while(k1 > i && reqStr[k1] != '/' && reqStr[k1] != ' ') --k1; // the URL suffix comes from [k1+1,k] // Copy "resultURLSuffix": if(k - k1 + 1 > resultURLSuffixMaxSize) return FALSE; // there's no room unsigned n = 0, k2 = k1+1; while(k2 <= k) resultURLSuffix[n++] = reqStr[k2++]; resultURLSuffix[n] = '\0'; // Also look for the URL 'pre-suffix' before this: unsigned k3 = --k1; while(k3 > i && reqStr[k3] != '/' && reqStr[k3] != ' ') --k3; // the URL pre-suffix comes from [k3+1,k1] // Copy "resultURLPreSuffix": if(k1 - k3 + 1 > resultURLPreSuffixMaxSize) return FALSE; // there's no room n = 0; k2 = k3+1; while(k2 <= k1) resultURLPreSuffix[n++] = reqStr[k2++]; resultURLPreSuffix[n] = '\0'; i = k + 7; // to go past " RTSP/" parseSucceeded = TRUE; break; } } if(!parseSucceeded) return FALSE; // Look for "CSeq:", skip whitespace, // then read everything up to the next \r or \n as 'CSeq': parseSucceeded = FALSE; for(j = i; j < reqStrSize-5; ++j) { if(reqStr[j] == 'C' && reqStr[j+1] == 'S' && reqStr[j+2] == 'e' && reqStr[j+3] == 'q' && reqStr[j+4] == ':') { j += 5; unsigned n; while(j < reqStrSize &&(reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; for(n = 0; n < resultCSeqMaxSize - 1 && j < reqStrSize; ++n, ++j) { char c = reqStr[j]; if(c == '\r' || c == '\n') { parseSucceeded = TRUE; break; } resultCSeq[n] = c; } resultCSeq[n] = '\0'; break; } } if(!parseSucceeded) return FALSE; return TRUE; } int OptionAnswer(char *cseq, int sock) { if(sock != 0) { char buf[1024]; memset(buf,0,1024); char *pTemp = buf; pTemp += sprintf(pTemp,"RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sPublic: %s\r\n\r\n", cseq,dateHeader(),"OPTIONS,DESCRIBE,SETUP,PLAY,PAUSE,TEARDOWN"); int reg = send(sock, buf, strlen(buf), 0); if(reg <= 0) { return FALSE; } else { printf(">>>>>%s\n", buf); } return TRUE; } return FALSE; } int DescribeAnswer(char *cseq,int s
评论
    相关推荐
    • 最新仙镜传说服务器c语言源码
      最新的仙镜传说服务器C语言源码,这是日本最新在布的,数据库类型为文件型数据库。 这个源码相当的完整,只要编译一次后就可以运行了,但得用到客户端的两个文件一个是data.grf另一个是sdata.grf,大家都可以试试!...
    • 守护进程时间服务器C语言实现.rar
      守护进程时间服务器C语言实现,适合编程小白
    • 最新仙镜传说服务器C语言源码
      最新的仙镜传说服务器C语言源码,这是日本最新在布的,数据库类型为文件型数据库。 这个源码相当的完整,只要编译一次后就可以运行了,但得用到客户端的两个文件一个是data.grf另一个是sdata.grf,大家都可以试试!
    • RTSP服务器C语言
      hi3516A输出h264码流,rtsp服务器完成推流,环形缓冲,异步监测。
    • http代理服务器C语言
      以前上TCP/IP课程时做的课程设计,很小的一个HTTP代理服务器,基于socket编程。VC6.0环境的。原创程序。 那时候还是新手,程序很简陋,不过好歹能用。 学校学习相关课程的学生可以参考下,当个课程作业没问题,老手...
    • 最新仙镜传说服务器C语言源码
      最新的仙镜传说服务器C语言源码,这是日本最新在布的,数据库类型为文件型数据库。这个源码相当的完整,只要编译一次后就可以运行了,但得用到客户端的两个文件一个是data.grf另一个是sdata.grf,大家都可以试试!我...
    • 最新仙镜传说服务器C语言源码.zip
      最新仙镜传说服务器C语言源码.zip为游戏源代码,作为开发游戏的一个很好DEMO
    • web服务器 C语言
      一个用C语言编写的WEB服务器,用socket编程
    • C语言并发服务器
      C语言并发服务器,包括客户端和服务器端。
    • GaussDB_100_1.0.1-DATABASE-REDHAT-64bit.tar.gz
      guassdb100在redhat上安装包,单机部署的包,安装步骤请看我的文中介绍,经过大量实验搭建总结出来的文档