简体   繁体   English

使用C通过TCP套接字处理映像

[英]Processing image over tcp socket with c

I have a small c program which connect and authenticate with my security DVR which in turn starts sending me data over the socket. 我有一个小型的c程序,该程序可以与我的安全DVR连接并进行身份验证,然后依次通过套接字向我发送数据。 I can connect on port 5000 or port 80 sending different authentification methods to start receiving the video/images. 我可以连接端口5000或端口80,以发送不同的身份验证方法来开始接收视频/图像。 My problem is; 我的问题是; I am new to c first of all, and I am very lost on how to process the data received over the socket. 首先,我是c的新手,我对如何处理通过套接字接收的数据非常迷茫。 This is the data I am sending to authenticate. 这是我发送的用于身份验证的数据。

char authenticate[] = {
    0x31, 0x31, 0x31, 0x31, 0x88, 0x00, 0x00, 0x00, 
    0x01, 0x01, 0x00, 0x00, 0x88, 0x7d, 0xa6, 0x47, 
    0x0c, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 
    0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x61, 0x64, 0x6d, 0x69, 0x6e, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x31, 0x32, 0x33, 0x34, 
    0x35, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x43, 0x6f, 0x6c, 0x74, 0x6f, 0x6e, 0x73, 0x2d, 
    0x4d, 0x61, 0x63, 0x42, 0x6f, 0x6f, 0x6b, 0x2d, 
    0x50, 0x72, 0x6f, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 
    0x6c, 0x00, 0x00, 0x00, 0x35, 0x34, 0x32, 0x36, 
    0x39, 0x36, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 
 };

  x = sendto(sockfd, authenticate, sizeof(authenticate), 0,
  (struct sockaddr*)&servaddr, sizeof(servaddr));

I am then recieving the data with 然后,我将接收数据

while(1)
{
  n = recvfrom(sockfd, data, 2048, 0, NULL, NULL);

When I connect via http port 80 This is the image data that I receive: 当我通过http端口80连接时,这是我收到的图像数据:

Content-length: 2153
Content-type: image/jpeg

ˇÿˇ‡JFIFHHˇ€Cˇ€Cˇ¿#ˇƒ  
    ˇƒ8 2A!$X"#3QRTqëîóò“’÷ˇƒˇƒ@   
        !1A"2QRqrë#SacÅ°¢≥—“ÒBCstÇí¥”ˇ⁄     ?e›n◊}mÀ⁄ÔÅ≥j¿ò[0ÂáֱNU…9'*‚®@ô &yéïùr‰Ù®{ï“däŒÆl$Kkë       R,√fƒSl—EX
    z   \û£≠âflüÈ‚≠ê*àÉ*—1E;q}Ìp6@>øÆÂòŸR≠^Ì˝çò ı;R∆b¡»ü>aÊ∫a˙5KKüz∑¶Î´D“≤κl∂ÎÓ„∆Àn∫¥•sh8vß4≠äöûñy‰H¢çyºí0TQrÏ@π dÅèåfi*XY*F¨Óƒl™¢‰˝S^sgh]î…flzXNü‡†2∑ñæ5t€Tp`qìåos◊iGùjˆ˙+FÈ™‚‘_§≈[”Jˇ     *•<*´∆≥ÁpVGfl
    ï¶ñ—€{ñgíJmd*ôï„å[YT-J†∞π∂¯ë…{¶dyÓaÓhå©!øg⁄∆™≤È:
    ≥Ô`Mú)∞ÚÌǯhˇÿ„Tø∑,9˛õ°˛ıØö~ø«ûÔ˝˙aa{ÜÔû÷Èé‡ÂΩk÷ºµ\sÉÒ¬XÓ∞`¯⁄X“">eäÅœ»G¡ìöÜ"˘mütòÅtuÓbÌh;vB1dflL ∂)
    ´È
    Hm∂Í
    Ω¡î*Ä≤e‘nÄï‘HΩ…77ÙIè6%â%ãµ"T¿n¢Í3%‹zj#™:”ÂmR˛=L  ZsZ[_ïz±»r…™2®ú.«]∑$q¢1)ùftÙ˘îà[q£°Îü&%Ï÷@á∂¿ôEy!ËÇJ0‚‚j»¥|∆fi–ü5"èRj›D˘„õUäú≥û>•«bdôãq]Ö$2ˆ„Gc#,ó±Ò<√-p}ZÍSÛ                                                          £ëóŒsäóNçı≠◊òÊö•mÈÇ_W„Y2∆∫9œxπŸ¸*±’dË⁄1(¸05{üfW∆Éû
    ‘ÿSÑ‘„û.JTÓ9˙Ìø˝∆º=∆        ¬ï∆h≥!`uˆ’Uçõèd„Ï…ı®*GÕıŸ6iíÆiñ¶’ØmBë‰WáÈö˛â‚ı∞>Ó˛◊_Â’ˇπ?º”˘øh~8TÔÕ/ùˆO¬Ewü^◊]…6
    ÕïÊ«p2ˆ◊ä”õU÷ËÖˆ◊䲲ãk–«_2ûk4Éÿ‰aÖƒîP∑ùg⁄†·¢µ’ÂS÷}XNï¯5GWæßGk”óS8fòˇ;˝âp;≈“ƒ5ˇ˜„Éû·&Áa¨ö2tÿ±íÉìcÇeÓ"¬Â„(8¯:øØíM    £rmfiá~≠æ(:oT/U≤/täó       U√ñT0ëªÕ      ê’¢víRT@˙‚ìO7ÖÆÒ‘D<dm@;F®—yÑmPǃ5É+FZÀ"8≥-˙7"ç–ãm{Å∑Öunü»à·®icëcoDìf¬·ñ)!å A¡ñÂNrx√aeP\ZM®£      ‘Y\<kJÿ‚’Ó#„Œª+â3
    ¨π©%Uü±Àñ¨œò§S2àŸßUJjwûYãZ@Ç∆˚¶&hr⁄xj¬ì  È™sàK-…  28Fm‡Ôr√û      8Qè
    ª∑ØP ptt£‚N—Œ∆Iπ ıo«Y{Èe.U[´‰•ı∫ÎæöÙU’‘…)¶Gy
    †“ä]ãä6U≤Å∞b 7X„        ™˙@ÓMÖ∑>_ó
    =fiÔ>·π∂ˇ÷ãÎΩfl«Y!µÎô≥—ß;¨J™èΩ|tLoîRˇM›.@nŸÍ±≈±Ê∏Ï~qkãsv≈Xõ‰í∞Lπ/cR,j*6.Sí„ÿ˘fÑ»7f|_™≥RçÿíE°°bã {{Ïõç#·Ãæ:7çú√´u      o
    ⁄N¨Ω\€ù◊K,Z4àÕ8N\˙πÍë’D∫vbfl∏¢>äz.¸¨⁄Ä‘°dx≈ªàˆÕ45‡ßõub-ü%TVTN8⁄∞¨≤µÁñÜD[;o—˘ƒNˇóóØ[ò;´¡O*∫¿ƒ©∏2ߘG#20˘H∆µªú’2€∂O°Â⁄Ùb®äÌ/hÿQÁXÓŸJzB¬Öw]Ù2ÿ—⁄§∆«gÜö·´˚Ëãt‚+˛Iì¯∂⁄nÎ{ºVʬ)aà∆´°ÀÚËÃkr÷â„ç^1©ôæ
    óv'ô8∆ãπkB˙цπ¯zÉsÀpv;Ã]ÓI€[Ìj/˙A≤øÒ}O˚ËS|Dûƒˇ¶3=ÓÍæ6?Ú…å!¥›¨Ûˆ¸f…€·I~à≥      g>∆®‰√Û0≥30®Æ) èMÖçGÃ∑dÑÖ∞¥Œéf≥ÔyµE¢Yå.õ·ç+r˙ú ≤ZÄP    ‰y¨Km⁄±~ävfl¡'I+b»Ñî[ö<¬        æñ8raEãk

I am unsure if this data is some weird encoding or if it need to be processed somehow to make it valid. 我不确定此数据是否是某种奇怪的编码,或者是否需要以某种方式进行处理以使其有效。 I have searched around with no luck or examples of how to properly do this. 我四处搜寻,没有运气或如何正确执行此操作的示例。 If i connect via the data port (port 5000 which sends via instead of an image) the data looks pretty much the same although i know it may be processed or unprocessed H.246 video data. 如果我通过数据端口(通过而不是通过图像发送的端口5000)连接,尽管我知道它可以处理或未处理的H.246视频数据,但数据看起来几乎相同。

The raw data is an image. 原始数据图像。 It starts after the blank line which terminate the headers. 它在终止标题的空白行之后开始。

Code: 码:

n = recvfrom(sockfd, data, 2048, 0, NULL, NULL); // might as well replace with read().  
// use a much larger buffer, ideally large enough to fit largest possible whole image

headers_end_str = "\r\n\r\n";
headers_end_position = strstr(data, headers_end_str);
headers_end_position += strlen(headers_end_str );

if (headers_end_position > n) { ... } // handle errors

FILE* fh = fopen("image.jpg", "wb");

int result = fwrite( &( data[ headers_end_position ), n - headers_end_position, 1, fh);
// check result for errors

// continue reading from socket and writing to file, subsequent reads do not have headers

This should get you started, you need to fine tune reading additional data, and also error handling and end of file. 这应该使您入门,您需要微调读取其他数据,以及错误处理和文件结尾。

However, even before you have done all that, you should be able to run "file -s image.jpg" (on linux, or cygwin) and it will tell you it's a JPEG image. 但是,即使在完成所有操作之前,您也应该能够运行“ file -s image.jpg”(在Linux或cygwin上),它将告诉您这是JPEG图像。

I used WireShark to monitor the communication between the DVR and it's web browser plugin client and the authentication message header is similar to your post (0x31 0x31 0x31 0x31...). 我使用WireShark来监视DVR及其Web浏览器插件客户端之间的通信,并且身份验证消息标题与您的帖子类似(0x31 0x31 0x31 0x31 ...)。 How did you construct this array? 您如何构造此数组? I searched a lot for this protocol documentation but I didn't find. 我在该协议文档中进行了大量搜索,但没有找到。

In my case I do the requests at port 7171 (it's a DVR settings). 以我为例,我在端口7171上执行请求(这是DVR设置)。 I also used a while(true) to keep listening this port and the server sends me a h264 stream. 我还使用了一阵(true)来继续监听此端口,服务器向我发送了h264流。

The problem is that the stream is not like rtps protocol describes, see this great post . 问题是流不像rtps协议描述的那样,请参阅这篇伟大的文章 In our case we have to parse a kind of proprietary header first (that starts with 0x31 0x31 0x31 0x31) to stract the frame, sps and pps. 在我们的案例中,我们必须首先解析一种专有报头(以0x31 0x31 0x31 0x31开头),以提取帧,sps和pps。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM