Ubuntu上 rtsp 服务器与客户端利用socket进行交互------创建了rtsp服务器(服务器端用tcp协议传输)
2021-09-01 17:02
1021 查看
代码功能
写了一个RTSP服务器:创建了TCP套接字(socket),并在RTSP服务器端创建了RTP、RTCP套接字(socket)
Ubuntu下VLC充当了RTSP客户端
参考
https://blog.csdn.net/weixin_42462202/article/details/99068041
1、测试代码
/* * Author:Frank */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <time.h> #define SERVER_PORT 8554 #define SERVER_RTP_PORT 55532 #define SERVER_RTCP_PORT 55533 #define BUF_MAX_SIZE (1024*1024) static int createTcpSocket() { int sockfd; int on = 1; sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd < 0) return -1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)); return sockfd; } static int createUdpSocket() { int sockfd; int on = 1; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd < 0) return -1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)); return sockfd; } static int bindSocketAddr(int sockfd, const char* ip, int port) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0) return -1; return 0; } static int acceptClient(int sockfd, char* ip, int* port) { int clientfd; socklen_t len = 0; struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); len = sizeof(addr); clientfd = accept(sockfd, (struct sockaddr *)&addr, &len); if(clientfd < 0) return -1; strcpy(ip, inet_ntoa(addr.sin_addr)); *port = ntohs(addr.sin_port); return clientfd; } static char* getLineFromBuf(char* buf, char* line) { while(*buf != '\n') { *line = *buf; line++; buf++; } *line = '\n'; ++line; *line = '\0'; ++buf; return buf; } 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: %d\r\n\r\n" "%s", cseq, url, strlen(sdp), sdp); return 0; } 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=60\r\n\r\n", cseq); return 0; } static void doClient(int clientSockfd, const char* clientIP, int clientPort, int serverRtpSockfd, int serverRtcpSockfd) { char method[40]; char url[100]; char version[40]; int cseq; int clientRtpPort, clientRtcpPort; char *bufPtr; char* rBuf = malloc(BUF_MAX_SIZE); char* sBuf = malloc(BUF_MAX_SIZE); char line[400]; while(1) { int recvLen; recvLen = recv(clientSockfd, rBuf, BUF_MAX_SIZE, 0); if(recvLen <= 0) goto out; rBuf[recvLen] = '\0'; printf("---------------C->S--------------\n"); printf("%s", rBuf); /* 解析方法 */ bufPtr = getLineFromBuf(rBuf, line); if(sscanf(line, "%s %s %s\r\n", method, url, version) != 3) { printf("parse err\n"); goto out; } /* 解析序列号 */ bufPtr = getLineFromBuf(bufPtr, line); if(sscanf(line, "CSeq: %d\r\n", &cseq) != 1) { printf("parse err\n"); goto out; } /* 如果是SETUP,那么就再解析client_port */ if(!strcmp(method, "SETUP")) { while(1) { bufPtr = getLineFromBuf(bufPtr, line); if(!strncmp(line, "Transport:", strlen("Transport:"))) { sscanf(line, "Transport: RTP/AVP;unicast;client_port=%d-%d\r\n", &clientRtpPort, &clientRtcpPort); break; } } } if(!strcmp(method, "OPTIONS")) { if(handleCmd_OPTIONS(sBuf, cseq)) { printf("failed to handle options\n"); goto out; } } else if(!strcmp(method, "DESCRIBE")) { if(handleCmd_DESCRIBE(sBuf, cseq, url)) { printf("failed to handle describe\n"); goto out; } } else if(!strcmp(method, "SETUP")) { if(handleCmd_SETUP(sBuf, cseq, clientRtpPort)) { printf("failed to handle setup\n"); goto out; } } else if(!strcmp(method, "PLAY")) { if(handleCmd_PLAY(sBuf, cseq)) { printf("failed to handle play\n"); goto out; } } else { goto out; } printf("---------------S->C--------------\n"); printf("%s", sBuf); send(clientSockfd, sBuf, strlen(sBuf), 0); } out: close(clientSockfd); free(rBuf); free(sBuf); } int main(int argc, char* argv[]) { int serverSockfd; int serverRtpSockfd, serverRtcpSockfd; int ret; serverSockfd = createTcpSocket(); if(serverSockfd < 0) { printf("failed to create tcp socket\n"); return -1; } ret = bindSocketAddr(serverSockfd, "0.0.0.0", SERVER_PORT); if(ret < 0) { printf("failed to bind addr\n"); return -1; } ret = listen(serverSockfd, 10); if(ret < 0) { printf("failed to listen\n"); return -1; } serverRtpSockfd = createUdpSocket(); serverRtcpSockfd = createUdpSocket(); if(serverRtpSockfd < 0 || serverRtcpSockfd < 0) { printf("failed to create udp socket\n"); return -1; } if(bindSocketAddr(serverRtpSockfd, "0.0.0.0", SERVER_RTP_PORT) < 0 || bindSocketAddr(serverRtcpSockfd, "0.0.0.0", SERVER_RTCP_PORT) < 0) { printf("failed to bind addr\n"); return -1; } printf("rtsp://127.0.0.1:%d\n", SERVER_PORT); while(1) { int clientSockfd; char clientIp[40]; int clientPort; clientSockfd = acceptClient(serverSockfd, clientIp, &clientPort); if(clientSockfd < 0) { printf("failed to accept client\n"); return -1; } printf("accept client;client ip:%s,client port:%d\n", clientIp, clientPort); doClient(clientSockfd, clientIp, clientPort, serverRtpSockfd, serverRtcpSockfd); } return 0; }View Code
2、测试前提
具体步骤如下:
2.1、需要提前在ubuntu下安装vlc播放器:
sudo apt-get install vlc
2.2、目前虚拟机网络配置:
rtsp://127.0.0.1:8554 accept client;client ip:127.0.0.1,client port:35106 ---------------C->S-------------- OPTIONS rtsp://127.0.0.1:8554 RTSP/1.0 CSeq: 2 User-Agent: LibVLC/2.2.2 (LIVE555 Streaming Media v2016.02.09) ---------------S->C-------------- RTSP/1.0 200 OK CSeq: 2 Public: OPTIONS, DESCRIBE, SETUP, PLAY ---------------C->S-------------- DESCRIBE rtsp://127.0.0.1:8554 RTSP/1.0 CSeq: 3 User-Agent: LibVLC/2.2.2 (LIVE555 Streaming Media v2016.02.09) Accept: application/sdp ---------------S->C-------------- RTSP/1.0 200 OK CSeq: 3 Content-Base: rtsp://127.0.0.1:8554 Content-type: application/sdp Content-length: 125 v=0 o=- 91630487295 1 IN IP4 127.0.0.1 t=0 0 a=control:* m=video 0 RTP/AVP 96 a=rtpmap:96 H264/90000 a=control:track0 ---------------C->S-------------- SETUP rtsp://127.0.0.1:8554/track0 RTSP/1.0 CSeq: 4 User-Agent: LibVLC/2.2.2 (LIVE555 Streaming Media v2016.02.09) Transport: RTP/AVP;unicast;client_port=45400-45401 ---------------S->C-------------- RTSP/1.0 200 OK CSeq: 4 Transport: RTP/AVP;unicast;client_port=45400-45401;server_port=55532-55533 Session: 66334873 ---------------C->S-------------- PLAY rtsp://127.0.0.1:8554 RTSP/1.0 CSeq: 5 User-Agent: LibVLC/2.2.2 (LIVE555 Streaming Media v2016.02.09) Session: 66334873 Range: npt=0.000- ---------------S->C-------------- RTSP/1.0 200 OK CSeq: 5 Range: npt=0.000- Session: 66334873; timeout=60 ---------------C->S-------------- TEARDOWN rtsp://127.0.0.1:8554 RTSP/1.0 CSeq: 6 User-Agent: LibVLC/2.2.2 (LIVE555 Streaming Media v2016.02.09) Session: 66334873View Code
相关文章推荐
- C#socket编程——TCP协议创建服务器端和客户端并进行通信
- Android客户端与PC服务器通过socket进行交互实例
- Linux C利用Socket套接字进行服务器与多个客户端进行通讯
- Android客户端与PC服务器通过socket进行交互实例(转)
- 网络编程(1)--利用socket进行客户端与服务器端的通信
- Android客户端与PC服务器通过socket进行交互实例
- 【Linux网络编程实例】实例二:利用TCP协议进行客户端与服务器通信
- 客户端和应用服务器之间利用HttpClient和Servlet交互JSON对象进行通信
- 多个客户端使用Socket通过一个服务器进行交互的小例子
- Android客户端与PC服务器通过socket进行交互实例
- Android客户端与服务器端通过SOCKET连接进行读写(将JSON数据转化为字符串后传输)
- Java_socket程序学习03-一个客户端对一个服务器-交互(服务器端)--01
- 利用C#进行socket编程(模拟服务器和客户端通信)
- Linux C利用Socket套接字进行服务器与多个客户端进行通讯
- 利用Flash作为桥梁连接WEB页面和服务器端Socket通信,达到服务器主动"推"客户端的效果
- Android客户端与PC服务器通过socket进行交互实例
- C#socket编程——UDP协议创建服务器端和客户端并进行通信
- socket连接 java服务器端 C#客户端进行交互 简单例子
- python:使用socket模块,进行服务器与客户端简单交互
- C++利用socket的客户端和服务器之间传输文件