国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

海康威視頻監控設備Web查看系統(二):服務器篇

2019-11-17 03:06:15
字體:
來源:轉載
供稿:網友

海康威視頻監控設備Web查看系統(二):服務器篇

聲明:本系列文章只提供交流與學習使用。文章中所有涉及到海康威視設備的SDK均可在海康威視官方網站下載得到。文章中所有除官方SDK意外的代碼均可隨意使用,任何涉及到海康威視公司利益的非正常使用由使用者自己負責,與本人無關。

前言:

上一篇文章《海康威視頻監控設備Web查看系統(一):概要篇》籠統的介紹了關于海康視頻中轉方案的思路,本文將一步步實現方案中的視頻中轉服務端。文中會涉及到一些.net socket處理和基礎的多線程操作。我用的是SDK版本是SDK_Win32_V4.2.8.1 。大家根據自己實際情況想在相應的SDK,頁面的說明里有詳細的設備型號列表。

分析官方SDK的Demo:

首先來看看官方SDK中的C#版本的Demo,官方Demo分為兩個版本,分別是“實時預覽示例代碼一”和“實時預覽示例代碼二”,因為有現成的C#版本,所以我們使用示例代碼一中的內容。首先關注名為CHCNetSDK的類,這個類封中裝了SDK中的所有非托管方法接口,我們需要來把這個類以及SDK中的DLL文件一起引入到我們的項目中,如果有對C#調用C++類庫不了解的朋友請自己Google一下,資料非常多,博客園里也有很多作者寫過這一類的文章,本文就不就這個內容做深入討論。

調用SDK沒有問題了,接下來看看SDK的使用,根據SDK使用文檔,SDK接口的調用需要通過一個標準流程,流程圖如下:

按照這個流程,我們第一步要做的是初始化SDK,然后是三個可選回調函數的設置,接著要做用戶注冊設備即設備登錄,緊接著就是核心的部分了,根據上一篇文章中講的思路,除了預覽模塊外其他幾個模塊的調用不在我們要解決的問題范疇,因此不予考慮。最后一步是注銷設備,釋放SDK資源。所以,最后根據我們的需求,流程簡化如下:

雖然標準流程如此,但是我們的服務端程序只有一個單一的任務,所以也沒有必要對為托管資源進行釋放,因為如果退出程序以后資源就會釋放,不退出程序的話,SDK資源就不應該被釋放。因此再簡化一下流程每個節點都有相應的代碼實現如如下所示:

 1 //初始化SDK 2 CHCNetSDK.NET_DVR_Init(); 3  4 //用戶登錄 5 CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30(); 6 CHCNetSDK.NET_DVR_Login_V30(設備ip地址, 設備端口, 用戶名, 密碼, ref DeviceInfo); 7 //說明:關于設備IP、端口、用戶名及密碼信息請根據自己要訪問設備的設置正確填寫 8  9 //預覽模塊10 CHCNetSDK.NET_DVR_CLIENTINFO lpClientInfo = new CHCNetSDK.NET_DVR_CLIENTINFO();11 lpClientInfo.lChannel = channel;12 lpClientInfo.lLinkMode = 0x0000;13 lpClientInfo.sMultiCastIP = "";14 m_fRealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack);15 IntPtr pUser = new IntPtr();16 CHCNetSDK.NET_DVR_RealPlay_V30(m_lUserID, ref lpClientInfo, m_fRealData, pUser, 1);17 //說明:這里的NET_DVR_CLIENTINFO類中缺少預覽窗口的句柄,需要預覽時,要根據自己的項目設置NET_DVR_CLIENTINFO對象的hPlayWnd屬性

可能有朋友看到這里已經忍受不了了,說好的視頻中轉功能在哪呢?別著急,一切的處理都在回調函數RealDataCallBack中,先耐心看一下這個回調函數的簽名

void RealDataCallBack(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser)

第一個lRealHandle是預覽控件的句柄,第二個參數dwDataType說明回調接收到的數據類型,pBuffer 存放數據的緩沖區指針, dwBufSize 緩沖區大小 ,pUser 用戶數據的句柄。我做的這個視頻的中轉功能其實就是在這個回調函數中實現的。

好了,核心的代碼都摘出來了,大家按照SDK提供的Demo照貓畫虎就可以把預覽功能實現出來了。

服務端設計:

  實現了預覽功能,下面看看中轉服務的實現。其中包含三個類:Server,Client以及ClientList類。

Server類主要負責從設備讀取數據并將數據緩存到服務器上,并且作為Socket監聽服務端;ClientList維護一個客戶端列表,并在Server獲取到設備數據時便利客戶端列表發送數據到客戶端;Client類主要負責將服務端緩存的數據分發到各個終端請求上。

三個類的關系及主要成員請看下圖:

Server類:

  1 class Server  2     {  3         int m_lUserID = -1;  4         //頭數據  5         byte[] headStream;  6   7         ClientList clientList = ClientList.GetClientList();  8         CHCNetSDK.REALDATACALLBACK m_fRealData;  9         Socket listenSocket; 10         Semaphore m_maxNumberAcceptedClients; 11         /// <summary> 12         /// Server構造函數,啟動服務端Socket及海康SDK獲取設備數據 13         /// </summary> 14         /// <param name="ipPoint">服務端IP配置</param> 15         /// <param name="numConnections">最大客戶端連接數</param> 16         /// <param name="channel">設備監聽通道</param> 17         public Server(IPEndPoint ipPoint, int numConnections, int channel) 18         { 19             if (!InitHK()) 20             { 21                 return; 22             } 23             RunGetStream(channel); 24  25             listenSocket = new Socket(ipPoint.AddressFamily, SocketType.Stream, PRotocolType.Tcp); 26             listenSocket.Bind(ipPoint); 27             m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections); 28             listenSocket.Listen(100); 29             Console.WriteLine("開始監聽客戶端連接......"); 30             StartAccept(null); 31         } 32  33         #region HKSDK 34  35         private void RunGetStream(int channel) 36         { 37             if (m_lUserID != -1)//初始化成功 38             { 39                 CHCNetSDK.NET_DVR_CLIENTINFO lpClientInfo = new CHCNetSDK.NET_DVR_CLIENTINFO(); 40                 lpClientInfo.lChannel = channel; 41                 lpClientInfo.lLinkMode = 0x0000; 42                 lpClientInfo.sMultiCastIP = ""; 43                 m_fRealData = new CHCNetSDK.REALDATACALLBACK(RealDataCallBack); 44                 IntPtr pUser = new IntPtr(); 45                 int m_lRealHandle = CHCNetSDK.NET_DVR_RealPlay_V30(m_lUserID, ref lpClientInfo, m_fRealData, pUser, 1); 46                 Console.WriteLine("開始獲取視頻數據......"); 47             } 48             else//初始化 失敗,因為已經初始化了 49             { 50                 Console.WriteLine("視頻數據獲取失敗......"); 51             } 52         } 53  54         private bool InitHK() 55         { 56             bool m_bInitSDK = CHCNetSDK.NET_DVR_Init(); 57             if (m_bInitSDK == false) 58             { 59                 return false; 60             } 61             else 62             { 63                 Console.WriteLine("設備SDK初始化成功......."); 64                 CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo = new CHCNetSDK.NET_DVR_DEVICEINFO_V30(); 65                 m_lUserID = CHCNetSDK.NET_DVR_Login_V30("設備IP", 連接端口, "連接用戶名", "連接密碼", ref DeviceInfo); 66                 if (m_lUserID != -1) 67                 { 68                     Console.WriteLine("監控設備登錄成功......."); 69                     return true; 70                 } 71                 else 72                 { 73                     Console.WriteLine("監控設備登錄失敗,稍后再試......."); 74                     return false; 75                 } 76             } 77         } 78  79         private void RealDataCallBack(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser) 80         { 81             byte[] data = new byte[dwBufSize]; 82             Marshal.Copy(pBuffer, data, 0, (int)dwBufSize); 83             Console.WriteLine("監控設備連接正常......"); 84             if (dwDataType == CHCNetSDK.NET_DVR_SYSHEAD) 85             { 86                 headStream = data; 87             } 88             clientList.SetSendData(data); 89             return; 90         } 91  92         #endregion 93  94         #region Socket 95         /// <summary> 96         /// 監聽客戶端 97         /// </summary> 98         /// <param name="acceptEventArg"></param> 99         private void StartAccept(SocketAsyncEventArgs acceptEventArg)100         {101             if (acceptEventArg == null)102             {103                 acceptEventArg = new SocketAsyncEventArgs();104                 acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);105             }106             else107             {108                 acceptEventArg.AcceptSocket = null;109             }110 111             m_maxNumberAcceptedClients.WaitOne();112             bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);113             if (!willRaiseEvent)114             {115                 ProcessAccept(acceptEventArg);116             }117         }118         /// <summary>119         /// 增加客戶端列表120         /// </summary>121         /// <param name="e"></param>122         private void ProcessAccept(SocketAsyncEventArgs e)123         {124             clientList.AddClient(new Client(e.AcceptSocket, headStream));125             StartAccept(e);126         }127 128         /// <summary>129         /// Socket回調函數130         /// </summary>131         /// <param name="
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 维西| 巍山| 个旧市| 马尔康县| 自治县| 蓝田县| 禄劝| 碌曲县| 新民市| 扎囊县| 丰镇市| 镇赉县| 天门市| 资溪县| 高淳县| 东港市| 泸州市| 上杭县| 宜春市| 开封市| 永春县| 泽州县| 盈江县| 建瓯市| 景泰县| 南汇区| 津市市| 金坛市| 潜江市| 西安市| 景泰县| 曲靖市| 泽普县| 高阳县| 安西县| 彰化县| 武陟县| 行唐县| 株洲市| 巩留县| 抚宁县|