C# 有这样的RTSP Ping吗?

C# 有这样的RTSP Ping吗?,c#,winforms,network-programming,rtsp,C#,Winforms,Network Programming,Rtsp,我目前正在开发一个WinForm应用程序,使用C#中的RTSP协议从IP摄像头流式传输视频。一切都很顺利。该应用程序的部分要求包括检查IP摄像头是否在线的功能 因此,我使用System.Net.NetworkInformation.ping类执行了ping函数来ping IP摄像头。假设相机的RTSP url如下:RTSP://[camera IP]:554/Master0 RTSP/1.0,我只需要提取[camera IP]部分并使用Ping类通过使用其IP查看相机是否在线 最初,它一直工作到

我目前正在开发一个WinForm应用程序,使用C#中的RTSP协议从IP摄像头流式传输视频。一切都很顺利。该应用程序的部分要求包括检查IP摄像头是否在线的功能

因此,我使用System.Net.NetworkInformation.ping类执行了ping函数来ping IP摄像头。假设相机的RTSP url如下:RTSP://[camera IP]:554/Master0 RTSP/1.0,我只需要提取[camera IP]部分并使用Ping类通过使用其IP查看相机是否在线

最初,它一直工作到出现问题,例如,如果输入的IP可能不是预期的IP摄像机(例如计算机的IP),如果输入的设备的IP在线,ping功能仍将工作


我试图搜索类似RTSP ping的东西,但找不到。我希望对此事有任何建议或意见。非常感谢C#中的任何示例。感谢您的关注。

您可能希望保持一个没有视频/音频RTP流的helper
RTSP
会话,而不是
ICMP
ping,检查套接字连接的良好状态,并定期发送
选项
描述
命令,例如每分钟一次,以查看设备是否响应

有人建议使用
GET_参数
代替选项,但这是一种较差的方法<代码>选项是必需的,
获取参数
不是必需的。两者都有不同的目的。两者的服务器端执行开销都很小<代码>选项显然是两者中的佼佼者

某些服务器可能不支持设置流参数,因此不支持GET_参数和SET_参数

关于C#中的RTSP,请参见此线程

关于平。。。您可以实现如下描述的操作。。。但注意不要使其过于频繁,设备应受到影响


选项
可能有效,但标准规定正确的方法是使用
GET\u参数

RFC2326清楚地概述了这一点

10.8获取参数

GET_参数请求检索 URI中指定的表示或流。答复的内容 而响应则留给实现。获取不带 实体主体可用于测试客户端或服务器活动性(“ping”)

虽然服务器可能不支持
GET\u参数
,但无法判断服务器将如何响应
选项
请求,该请求甚至不需要会话ID。因此,不能保证它将保持现有会话的活动状态

这一点在阅读关于
选项
请求的相同RFC时可以清楚地看到

10.1选择

该行为等同于[H9.2]中所述的行为。选择权 请求可以在任何时候发出,例如,如果客户即将 尝试一个非标准的请求。它不影响服务器状态

例如:

 C->S:  OPTIONS * RTSP/1.0
        CSeq: 1
        Require: implicit-play
        Proxy-Require: gzipped-messages

 S->C:  RTSP/1.0 200 OK
        CSeq: 1
        Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE
请注意,这些都是虚构的特征(人们希望如此) 我们不会故意忽略一个真正有用的特性 因此,我们可以在本节中有一个强有力的例子)

如果GET_参数不受支持,那么您将使用要保持活动状态的会话的SessionId发出播放请求

即使选项不符合会话ID,并且如果您已经在玩,也不会产生任何不利影响,这也应该有效

有关C#RtspClient的信息,请参见我的项目@

关于CodeProject@

的文章,您可以使用并执行以下操作:

public static async Task TestRTSPConnection(string rtspAddress, string user, string password)
{
        var serverUri = new Uri(rtspAddress);
        var credentials = new NetworkCredential(user, password);

        var connectionParameters = new ConnectionParameters(serverUri, credentials);
        var cancellationTokenSource = new CancellationTokenSource();

        var connectTask = ConnectAsync(connectionParameters, cancellationTokenSource.Token);

        if (await Task.WhenAny(connectTask, Task.Delay(15000 /*timeout*/)) == connectTask)
        {
            if (!connectTask.Result)
            {
                logger.Warn("Connection refused - check username and password");
            }

            logger.Info("Connection test completed");
        }
        else 
        {
            logger.Warn("Connection timed out - check username and password");
        }
    }

    private static async Task<bool> ConnectAsync(ConnectionParameters connectionParameters, CancellationToken token)
    {
        try
        {
            using (var rtspClient = new RtspClient(connectionParameters))
            {
                rtspClient.FrameReceived +=
                    (sender, frame) => logger.Info($"New frame {frame.Timestamp}: {frame.GetType().Name}");

                while (true)
                {
                    logger.Info("Connecting...");

                    try
                    {
                        await rtspClient.ConnectAsync(token);
                    }
                    catch (OperationCanceledException)
                    {
                        logger.Info("Finishing test before connection could be established. Check credentials");
                        return false;
                    }
                    catch (RtspClientException e)
                    {
                        logger.Error($"{e.Message}: {e.InnerException?.Message}");
                        return false;
                    }

                    logger.Info("Connected - camera is online");
                    return true;
                }
            }
        }
        catch (OperationCanceledException)
        {
            return false;
        }
    }
公共静态异步任务TestRTSPConnection(字符串rtspAddress、字符串用户、字符串密码)
{
var serverUri=新的Uri(rtspAddress);
var凭证=新的网络凭证(用户、密码);
var connectionParameters=新的connectionParameters(serverUri,凭证);
var cancellationTokenSource=新的cancellationTokenSource();
var connectTask=ConnectAsync(connectionParameters,cancellationTokenSource.Token);
if(wait Task.wheny(connectTask,Task.Delay(15000/*timeout*/)==connectTask)
{
如果(!connectTask.Result)
{
logger.Warn(“连接被拒绝-检查用户名和密码”);
}
logger.Info(“连接测试完成”);
}
其他的
{
logger.Warn(“连接超时-检查用户名和密码”);
}
}
专用静态异步任务ConnectAsync(ConnectionParameters ConnectionParameters,CancellationToken令牌)
{
尝试
{
使用(var rtspClient=new rtspClient(connectionParameters))
{
rtspClient.FrameReceived+=
(sender,frame)=>logger.Info($“新帧{frame.Timestamp}:{frame.GetType().Name}”);
while(true)
{
logger.Info(“连接…”);
尝试
{
等待rtspClient.ConnectAsync(令牌);
}
捕获(操作取消异常)
{
Info(“在建立连接之前完成测试。检查凭据”);
返回false;
}
捕获(RtspClientException e)
{
logger.Error($“{e.Message}:{e.InnerException?.Message}”);
返回false;
}
logger.Info(“已连接-摄像头处于联机状态”);
返回true;
}
}
}
捕获(操作取消异常)
{
返回false;
}
}
如果你只关心pin的话,这对我很有用