IT技术互动交流平台

CYG视频服务器之代码解释

作者:草根老师  发布日期:2013-03-18 19:31:41
1.和浏览器交互的线程
void *client_thread(void *arg) 
{ 
request_t request = {0}; 
char buf[1024] = {0}; 
client_t *pclient = (client_t *)arg; 
//接受浏览器发过来的请求 
if(recv(pclient->connect_fd,buf,sizeof(buf) -1,0) < 0) 
{ 
perror("Fail to recv"); 
pthread_exit(NULL); 
} 


//分析请求 
if(analysis_http_request(buf,&request) < 0){ 
pthread_exit(NULL); 
} 


//应答浏览器 www.it165.net
switch(request.type) 
{ 
case A_FILE: 
send_file(pclient->connect_fd,request.parm,pclient->www_dir); 
break; 


case A_SNAPSHOT: 
send_snapshot(pclient->connect_fd); 
break; 


case A_STREAM: 
send_stream(pclient->connect_fd); 
break; 
} 


close(pclient->connect_fd); 
free(pclient->www_dir); 
printf("free pclient->www_dir ok.\n"); 
free(pclient); 
printf("free pclient ok.\n"); 
free(request.parm); 
printf("free request.parm ok.\n"); 


return NULL; 
} 

2.接受客户端发送的请求
 

int accept_http_request(int sockfd,char *buf) 
{ 
fd_set fds; 
int ret; 
int n = 0,offset = 0; 
struct timeval tv = {5,0}; 


while(1) 
{ 
FD_ZERO(&fds); 
FD_SET(sockfd,&fds); 


if((ret = select(sockfd + 1,&fds,NULL,NULL,&tv)) <= 0) 
{ 
if(ret < 0){ 
perror("Fail to select"); 
return -1; 
} 


break; 
} 
if((n = recv(sockfd,buf + offset,BUFFER_SIZE - offset,0)) < 0) 
{ 
perror("Fail to recv"); 
return -1; 
} 
#if 0 
printf("***********************************\n"); 
printf("%s\n",buf); 
printf("***********************************\n"); 
#endif  
offset += n; 


if(offset >= sizeof(buf) - 1) 
break; 
} 
return 0; 
} 

3.分析请求的内容
 

int analysis_http_request(char *buf,request_t *req) 
{ 
int len = 0; 
char *p = NULL; 


/* determine what to deliver */ 
if ( strstr(buf, "GET /?action=snapshot") != NULL ) { 
req->type = A_SNAPSHOT; 
return 0; 
}else if ( strstr(buf, "GET /?action=stream") != NULL ) { 
req->type = A_STREAM; 
return 0; 
}else{ 


if((p = strstr(buf,"GET /")) == NULL) 
{ 
printf("Http request error.\n"); 
//send error to client 
return -1; 
} 


p += strlen("GET /"); 
len = MIN(MAX(strspn(p, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-1234567890"), 0), 100); 
req->parm = (char *)malloc(len + 1); 
memset(req->parm,0,len+1); 
memcpy(req->parm,p,len); 
printf("req->parm : %s.\n",req->parm); 
req->type = A_FILE; 
} 


return 0; 
} 

4.发送一副静态图片
 

void send_snapshot(int sockfd) 
{ 
int length; 
char *frame; 
char buf[BUFFER_SIZE]; 


pthread_mutex_lock(&global.update_lock); 


pthread_cond_wait(&global.update_cond,&global.update_lock); 
//获得视频数据 
length = global.length; 
frame  = (char *)malloc(global.length); 
memcpy(frame,global.start,global.length); 
pthread_mutex_unlock(&global.update_lock); 


//添加http头 
    memset(buf,0,sizeof(buf)); 
sprintf(buf, "HTTP/1.0 200 OK\r\n" \ 
                 "Content-type: image/jpeg\r\n" \ 
                 STD_HEADER \ 
           "\r\n"); 


//发送http头 
if(send(sockfd,buf,strlen(buf),0) < 0) 
{ 
free(frame); 
return; 
} 


//发送视频数据   
if(send(sockfd,frame,length,0) < 0) 
{ 
free(frame); 
return; 
} 


free(frame); 


return; 
} 

5.发送视频流
 

void send_stream(int sockfd) 
{ 
int length; 
char *frame; 
char buf[BUFFER_SIZE]; 
printf("send_stream\n"); 


   sprintf(buf, "HTTP/1.1 200 OK\r\n" \ 
                  STD_HEADER \ 
                  "Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY "\r\n" \ 
                  "\r\n" \ 
                  "--" BOUNDARY "\r\n"); 
//send to http head  
if(send(sockfd,buf,strlen(buf),0) < 0) 
{ 
perror("fail to send http head"); 
return; 
} 


printf("send http head ok\n"); 
while(!global.stop) 
{ 
pthread_mutex_lock(&global.update_lock); 
pthread_cond_wait(&global.update_cond,&global.update_lock); 
//获得视频数据 
length = global.length; 
frame  = (char *)malloc(global.length); 
memcpy(frame,global.start,global.length); 
pthread_mutex_unlock(&global.update_lock); 
/* print the individual mimetype and the length 
 * sending the content-length fixes random stream disruption observed 
 * with firefox 
 */ 
sprintf(buf, "Content-Type: image/jpeg\r\n" \ 
"Content-Length: %d\r\n" \ 
"\r\n",length); 
//sending intermdiate header 
if(send(sockfd,buf,strlen(buf),0) < 0) 
{ 
perror("Fail to send intermdiate header"); 
return; 
} 


printf("send intermdiate header.\n"); 
//sending camera frame  
if(send(sockfd,frame,length,0) < 0) 
{ 
perror("Fail to send camera frame"); 
return; 
} 


sprintf(buf, "\r\n--" BOUNDARY "\r\n"); 
if ( send(sockfd, buf, strlen(buf),0) < 0 ) break; 
free(frame); 
} 


return; 
} 

6.发送普通文件
 

void send_file(int sockfd,char *pathfile,char *www_dir) 
{ 
int n,fd,i; 
char buf[1024] = {0}; 
    char *extension, *mimetype=NULL; 
     
if(pathfile == NULL || strlen(pathfile) == 0) 
pathfile = "index.html"; 
    /* find file-extension */ 
    if ( (extension = strstr(pathfile, ".")) == NULL ) { 
    //    send_error(fd, 400, "No file extension found"); 
        return; 
    } 


    /* determine mime-type */ 
    for ( i=0; i < LENGTH_OF(mimetypes); i++ ) { 
        if ( strcmp(mimetypes[i].dot_extension, extension) == 0 ) { 
            mimetype = (char *)mimetypes[i].mimetype; 
            break; 
        } 
    } 
     
    /* in case of unknown mimetype or extension leave */ 
    if ( mimetype == NULL ) { 
    //    send_error(fd, 404, "MIME-TYPE not known"); 
        return; 
    } 


//打开文件  
sprintf(buf,"%s/%s",www_dir,pathfile); 
if((fd = open(buf,O_RDONLY)) < 0) 
{ 
fprintf(stderr,"Fail to open %s : %s.\n",buf,strerror(errno)); 
//send error to webbrowser 
return; 
} 


// printf("pathfile : %s.\n",buf); 


//添加http头 
    memset(buf,0,sizeof(buf)); 
sprintf(buf, "HTTP/1.0 200 OK\r\n" \ 
                 "Content-type: %s\r\n" \ 
                 STD_HEADER \ 
                 "\r\n",mimetype); 
    n = strlen(buf); 
//发送http头信息和网页 
do{ 
send(sockfd,buf,n,0); 
}while(n = read(fd,buf,sizeof(buf))); 


return; 

 

Tag标签: CYG   视频服务器   代码解释  
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规