8-5-1_编写简单RTSP协议-主流程

编写一个简单的RTSP协议-主流程

参考资料:

在开始我们先了解实现RTSP协议的流程:

  1. 创建RTSP服务器套接字
    1. 创建套接字
    2. 绑定套接字到指定地址和端口
    3. 监听端口
  2. 创建RTP和RTCP套接字,并监听对应的端口。
  3. 接受客户端连接,并获取IP地址和端口号。
  4. 处理客户端请求和解析。

程序编译与运行:

gcc h264_rtsp_server.c rtp.c -o demo

安装Linux版本的VLC:

sudo apt-get install vlc -y

将test.h264码流文件放在程序的同级目录下并运行程序:

./demo 
rtsp://127.0.0.1:8554

打开vlc程序,并将运行后打开的url地址即可播放码流。

1.创建TCP服务器

RTSP 服务器需要一个 TCP 套接字来与客户端进行通信。通过创建 TCP 套接字,服务器能够监听来自客户端的连接请求。

serverSockfd = createTcpSocket();
if(serverSockfd < 0)
{
    printf("failed to create tcp socket\n");
    return -1;
}

服务器需要绑定到一个特定的 IP 地址和端口,以便客户端知道如何连接到服务器。绑定到 "0.0.0.0" 表示服务器将监听所有可用的网络接口上的指定端口(SERVER_PORT)。

 if(bindSocketAddr(serverSockfd, "0.0.0.0", SERVER_PORT) < 0)
    {
        printf("failed to bind addr\n");
        return -1;
    }

在创建和绑定套接字之后,服务器可以调用 listen 函数开始监听连接请求,并使用 accept 函数接受客户端的连接。

    if(listen(serverSockfd, 10) < 0)
    {
        printf("failed to listen\n");
        return -1;
    }

2.创建RTP和RTCP套接字

创建 RTP 和 RTCP 的 UDP 套接字,准备传输通道:

  • RTP 套接字:用于传输实时音视频数据。RTSP 服务器需要一个 RTP 套接字来发送音视频流给客户端。
  • RTCP 套接字:用于传输控制信息,如质量反馈和同步信息。RTSP 服务器需要一个 RTCP 套接字来接收和发送这些控制信息。
    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;
    }

3.接受客户端连接

RTSP 服务器需要接受客户端的连接请求,以便与客户端进行通信。在接受连接的同时,服务器获取了客户端的 IP 地址和端口号。一旦连接建立,服务器可以开始处理客户端的 RTSP 请求,如播放、暂停、停止等操作。

        int clientSockfd;
        char clientIp[40];
        int clientPort;

        clientSockfd = acceptClient(serverSockfd, clientIp, &clientPort);
        if(clientSockfd < 0)
        {
            printf("failed to accept client\n");
            return -1;
        }

4.处理客户端请求

处理客户端的RTSP请求,并根据不同的请求类型执行相应的操作

doClient(clientSockfd, clientIp, clientPort, serverRtpSockfd, serverRtcpSockfd);

处理客户端请求:接收并解析客户端发送的 RTSP 请求,根据请求类型执行相应的操作。

发送响应:生成并发送 RTSP 响应数据给客户端,确保客户端能够正确接收到服务器的响应。

传输媒体数据:在接收到 PLAY 请求后,通过 RTP 协议将媒体数据(如视频帧)发送给客户端,实现实时流媒体传输。

主函数的处理流程为:

  1. 接收和解析客户端请求
    • 通过 recv 函数接收客户端发送的 RTSP 请求数据,并将其存储在缓冲区 rBuf 中。
    • 使用 getLineFromBuf 函数逐行解析请求数据,提取请求方法、URL、版本和序列号(CSeq)。
  2. 处理不同的 RTSP 方法
    • 根据解析出的请求方法(如 OPTIONSDESCRIBESETUPPLAY),调用相应的处理函数(如 handleCmd_OPTIONShandleCmd_DESCRIBEhandleCmd_SETUPhandleCmd_PLAY)。
    • 每个处理函数会生成相应的响应数据,并将其存储在发送缓冲区 sBuf 中。
  3. 发送响应给客户端
    • 将生成的响应数据通过 send 函数发送给客户端。
  4. 处理 PLAY 请求并发送 RTP 数据
    • 如果请求方法是 PLAY,则开始读取 H.264 文件中的视频帧,并通过 RTP 协议将视频帧发送给客户端。
    • 使用 rtpSendH264Frame 函数发送 RTP 包,并更新 RTP 包头中的时间戳。
    • 使用 usleep 函数控制发送帧的间隔时间,以模拟实时播放。
  5. 清理资源
    • 在处理完成或发生错误时,关闭客户端套接字并释放分配的内存。