通过isapi协议抓拍图片

PC端通过isapi协议抓拍摄像头图片

说明:
1、isapi协议类似于http协议
2、通过isapi协议抓拍图片要经过这几个步骤
2.1、先创建socket,再连接服务器(也就是摄像机)connect
2.2、发送没有认证得请求send
2.3、服务器响应401,根据www-Authenticate返回来得属性值,生成摘要认证
2.4、再次发送带有认证得请求
2.5、服务器响应400。

**以下是实现得代码:
tcpclient.cpp

#ifndef WINDOWS
#define WINDOWS
#endif

#ifdef WINDOWS
#include<WINSOCK2.H>
#include <WS2tcpip.h>  
#else
#include <iconv.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#endif 

#ifdef WINDOWS
#pragma warning(disable:4996) 
#pragma comment(lib, "WS2_32.lib")
#endif 

#include <errno.h>
#include <string.h>
#include "httpauth.h"

char * url = (char*)"/ISAPI/Streaming/channels/101/picture";
char * cmd = (char*)"GET";
const char * username_t = "admin";
const char * passworld_t = "znrt8899";
const char * realm_t = "DS-2CD7A27EWD-IZS";
const char * nonce_t = "4d6a46444d7a5a464e3045364e5449355a546c695932553d";
const char * nc_t = "00000001";
const char * cnonce_t = "8887920ea7e5c1c8";
const char * response_t = "5a9aa58fb654e667ad9d8e8adaa336df";
const char * qop_t = "auth";

FILE *fp = NULL;

void initialization();
int main(int argc, char * argv[])
{
	int sd, ret;
	char rcv_buf[1024*1024] = {0};
	struct sockaddr_in ser_sockaddr;
	int cnt = 0;
	
	httpauth_t auth;
	initialization();
	while (1)
	{
		//返回套接字描述符
		sd = socket(AF_INET, SOCK_STREAM, 0); //创建socket连接 选择IPV4的TCP协议数据包
		if (sd == -1)
		{
			printf("TCP套接字创建失败\r\n");
		}

		//设置sockaddr_in结构体中相关参数
		ser_sockaddr.sin_family = AF_INET;                                        //地址族 IPV4
	    ser_sockaddr.sin_port = htons(80);                                        //设置为要连接的服务器的端口号(short数据转化为网络数据)
		ser_sockaddr.sin_addr.s_addr = inet_addr("192.168.0.200");                //设置服务器的IP地址(字符串转化为整形)
        ret = connect(sd, (struct sockaddr *)&ser_sockaddr, sizeof(ser_sockaddr));//连接服务器
		if (ret == -1)
		{
			printf("连接服务器失败\r\n");
			return -1;
		}
		    printf("连接服务器成功\r\n");

			//struct timeval timeout = { 10, 0 };
		if (cnt == 0) 
		{
			httpauth_set_auth(&auth, username_t, passworld_t, realm_t, nonce_t, nc_t, cnonce_t, response_t, qop_t);
			request(sd, &auth, 0);
			recv(sd, rcv_buf, 1024, 0);
			printf("%s\r\n", rcv_buf);
			prase_response(rcv_buf, &auth);
		}
		else 
		{
			int rs = 1;
			int buflen = 0;
			int rev_pos = 0;
			int len;
			int jpeg_len;
			httpauth_get_response(&auth, cmd, url);
			memset(rcv_buf, 0, 1024);
			request(sd, &auth, 1);
			Sleep(1);

			len = sizeof(rcv_buf);
			while (rs)
			{
				buflen = recv(sd, &rcv_buf[rev_pos], len - rev_pos, 0);
				printf("%s\r\n", rcv_buf);
				printf("buflen is %d \r\n", buflen);
				printf("rcv_buf is %d \r\n", sizeof(rcv_buf));
				if (buflen < 0)
				{
					// 由于是非阻塞的模式,所以当buflen为EAGAIN时,表示当前缓冲区已无数据可读
					// 在这里就当作是该次事件已处理
					if (errno == EINTR)
						continue;
					else
						break;
				}
				else if (buflen == 0)
				{
					// 这里表示对端的socket已正常关闭.
					char *begin = NULL;
					begin = strstr(rcv_buf, "Content-Length:");
					jpeg_len = atoi(begin + 15);
					begin = strstr(rcv_buf, "\r\n\r\n");
					fp = fopen("./pic.JPEG", "wb");
					fwrite(begin + 4, jpeg_len, 1, fp);
	
				}

				if (buflen != 0)
					rs = 1;
				else
					rs = 0;
				    rev_pos += buflen;
			}
			   return 0;
		}

		closesocket(sd);
		cnt++;
		
	}
	return 0;
}
void initialization() {
	//初始化套接字库
	WORD w_req = MAKEWORD(2, 2);//版本号
	WSADATA wsadata;
	int err;
	err = WSAStartup(w_req, &wsadata);
	if (err != 0) {
		printf("初始化套接字库失败!");
	}
	else {
		printf("初始化套接字库成功!");
	}
	//检测版本号
	if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
		printf("套接字库版本号不符!");
		WSACleanup();
	}
	else {
		printf("套接字库版本正确!");
	}

}

httpauth.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define ISspace(x) isspace((int)(x)) 
#define USERLEN 33
#define REALMLEN 64
#define QOPLEN   32
typedef struct httpauth_t {
	char username[USERLEN], password[USERLEN];
	char qop[QOPLEN], realm[QOPLEN], nc[QOPLEN];
	char cnonce[REALMLEN], response[REALMLEN], nonce[REALMLEN];
}httpauth_t;

void to_hex(char *in, int len, unsigned char *out);
void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest);

int httpauth_set_auth(httpauth_t *auth, const char* username, const char* password, const char* realm, const char* nonce, const char* nc, const char* cnonce, const char* response, const char* qop);
int httpauth_get_response(httpauth_t *auth, char *cmd, char *url);
void request(int socket_fd, httpauth_t *auth, int flag);
int prase_response(char * response_buf, httpauth_t *auth);

httpauth.cpp

#include "httpauth.h"

#ifndef WINDOWS
#define WINDOWS
#endif

#ifdef WINDOWS
#include<WINSOCK2.H>
#include <WS2tcpip.h>  
#else
#include <iconv.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#endif // WINDOWS

#ifdef WINDOWS
#pragma warning(disable:4996) 
#pragma comment(lib, "WS2_32.lib")
#endif // WINDOWS
const uint32_t k[64] = {
	0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
	0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
	0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
	0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
	0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
	0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
	0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
	0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
	0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
	0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
	0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
	0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
	0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
	0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
	0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
	0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };

// r specifies the per-round shift amounts
const uint32_t r[] = {
	7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
	5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
	4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
	6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
};


// leftrotate function definition
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))




void to_bytes(uint32_t val, uint8_t *bytes)
{
	bytes[0] = (uint8_t)val;
	bytes[1] = (uint8_t)(val >> 8);
	bytes[2] = (uint8_t)(val >> 16);
	bytes[3] = (uint8_t)(val >> 24);
}

uint32_t to_int32(const uint8_t *bytes)
{
	return (uint32_t)bytes[0]
		| ((uint32_t)bytes[1] << 8)
		| ((uint32_t)bytes[2] << 16)
		| ((uint32_t)bytes[3] << 24);
}

void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) {
	// These vars will contain the hash
	uint32_t h0, h1, h2, h3;

	// Message (to prepare)
	uint8_t *msg = NULL;

	size_t new_len, offset;
	uint32_t w[16];
	uint32_t a, b, c, d, i, f, g, temp;

	// Initialize variables - simple count in nibbles:
	h0 = 0x67452301;
	h1 = 0xefcdab89;
	h2 = 0x98badcfe;
	h3 = 0x10325476;

	//Pre-processing:
	//append "1" bit to message    
	//append "0" bits until message length in bits � 448 (mod 512)
	//append length mod (2^64) to message

	for (new_len = initial_len + 1; new_len % (512 / 8) != 448 / 8; new_len++)
		;

	msg = (uint8_t*)malloc(new_len + 8);
	memcpy(msg, initial_msg, initial_len);
	msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first"
	for (offset = initial_len + 1; offset < new_len; offset++)
	msg[offset] = 0; // append "0" bits

	// append the len in bits at the end of the buffer.
	to_bytes(initial_len * 8, msg + new_len);
	// initial_len>>29 == initial_len*8>>32, but avoids overflow.
	to_bytes(initial_len >> 29, msg + new_len + 4);

	// Process the message in successive 512-bit chunks:
	//for each 512-bit chunk of message:
	for (offset = 0; offset < new_len; offset += (512 / 8)) {
		// break chunk into sixteen 32-bit words w[j], 0 � j � 15
		for (i = 0; i < 16; i++)
			w[i] = to_int32(msg + offset + i * 4);

		// Initialize hash value for this chunk:
		a = h0;
		b = h1;
		c = h2;
		d = h3;

		// Main loop:
		for (i = 0; i < 64; i++) {
			if (i < 16) {
				f = (b & c) | ((~b) & d);
				g = i;
			}
			else if (i < 32) {
				f = (d & b) | ((~d) & c);
				g = (5 * i + 1) % 16;
			}
			else if (i < 48) {
				f = b ^ c ^ d;
				g = (3 * i + 5) % 16;
			}
			else {
				f = c ^ (b | (~d));
				g = (7 * i) % 16;
			}

			temp = d;
			d = c;
			c = b;
			b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]);
			a = temp;
		}

		// Add this chunk's hash to result so far:
		h0 += a;
		h1 += b;
		h2 += c;
		h3 += d;
	}

	// cleanup
	free(msg);

	//var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
	to_bytes(h0, digest);
	to_bytes(h1, digest + 4);
	to_bytes(h2, digest + 8);
	to_bytes(h3, digest + 12);
}

void to_hex(char *in, int len, unsigned char *out)
{
	static char const hex[] = "0123456789abcdef";
	unsigned i;

	memset(out, 0, len * 2 + 1);

	for (i = 0;i < len;i++)
	{
		out[2 * i] = hex[(in[i] >> 4) & 0x0F];
		out[2 * i + 1] = hex[(in[i] & 0x0F)];
		//printf("%d#%2.2x##%2.2x###%2.2x\n",i,in[i],out[2*i],out[2*i+1]);
	}
}

int httpauth_set_auth(httpauth_t *auth, const char* username, const char* password, const char* realm, const char* nonce, const char* nc, const char* cnonce, const char* response, const char* qop)
{
	strcpy(auth->username, username);
	strcpy(auth->password, password);
	strcpy(auth->realm, realm);
	strcpy(auth->nonce, nonce);
	strcpy(auth->nc, nc);
	strcpy(auth->cnonce, cnonce);
	strcpy(auth->response, response);
	strcpy(auth->qop, qop);
	return 0;
}

int httpauth_get_response(httpauth_t *auth, char *cmd, char *url)
{
	uint8_t strH1[512], strH2[512];
	uint8_t md5_h1[33], md5_h2[33];
	uint8_t result[16], result2[16];
	size_t len;

	//md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<url>))
	memset(strH1, 0, 512);
	sprintf((char*)strH1, "%s:%s:%s", auth->username, auth->realm, auth->password);
	len = strlen((char*)strH1);
	md5(strH1, len, result);
	to_hex((char*)result, 16, md5_h1);
    memset(strH2, 0, 512);
	sprintf((char*)strH2, "%s:%s", cmd, url);
	len = strlen((char*)strH2);
	md5(strH2, len, result2);
	to_hex((char*)result2, 16, md5_h2);


	memset(strH1, 0, 512);
	sprintf((char*)strH1, "%s:%s:%s:%s:%s:%s", md5_h1, auth->nonce, auth->nc, auth->cnonce, auth->qop, md5_h2);
	//	printf("response %s\r\n",strH1);
	len = strlen((char*)strH1);
	md5(strH1, len, result);
	to_hex((char*)result, 16, (unsigned char *)auth->response);
	//	printf("response = %s\r\n",auth->response);
    return 0;
}

/**********************************************************************/
/* send a no authentication request */
/**********************************************************************/
void request(int socket_fd, httpauth_t *auth, int flag)
{
	char buf[2048];
	int pos = 0;
    pos = sprintf(&buf[pos], "GET /ISAPI/Streaming/channels/101/picture HTTP/1.1\r\n");
	pos += sprintf(&buf[pos], "Host:192.168.0.200\r\n");
	pos += sprintf(&buf[pos], "Connection: keep-alive\r\n");
	pos += sprintf(&buf[pos], "Cache-Control: max-age=0\r\n");
	if (1 == flag)
	{
		pos += sprintf(&buf[pos], "Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"/ISAPI/Streaming/channels/101/picture\", response=\"%s\", qop=auth, nc=00000001, cnonce=\"%s\"\r\n", auth->username, auth->realm, auth->nonce, auth->response, auth->cnonce);
	}
	    pos += sprintf(&buf[pos], "Upgrade-Insecure-Requests: 1\r\n");
	    pos += sprintf(&buf[pos], "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36\r\n");
	    pos += sprintf(&buf[pos], "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n");
	    pos += sprintf(&buf[pos], "Accept-Encoding: gzip, deflate, sdch\r\n");
	    pos += sprintf(&buf[pos], "Accept-Language: zh-CN,zh;q=0.9\r\n");
	    pos += sprintf(&buf[pos], "Cookie: language=zh\r\n");
	    pos += sprintf(&buf[pos], "\r\n");
	    printf("%s\r\n", buf);
	    int len = send(socket_fd, buf, strlen(buf), 0);
	    printf("发送长度是%d", len);
	

}

/**********************************************************************
int prase_response(char * response_buf )
**********************************************************************/

int prase_response(char * response_buf, httpauth_t *auth)
{
	    char * begin = NULL, *end = NULL;
	   if (strstr(response_buf, "401") != NULL)
	   {
			begin = strstr(response_buf, "\"");
			end = strstr(begin + 1, "\"");
			memcpy(auth->qop, begin + 1, end - begin - 1);
			auth->qop[end - begin - 1] = 0;
			begin = strstr(end + 1, "\"");
			end = strstr(begin + 1, "\"");
			memcpy(auth->realm, begin + 1, end - begin - 1);
			auth->realm[end - begin - 1] = 0;
			begin = strstr(end + 1, "\"");
			end = strstr(begin + 1, "\"");
			memcpy(auth->nonce, begin + 1, end - begin - 1);
			memcpy(auth->cnonce, auth->nonce, 16);
	   }
		
	
	else if (strstr(response_buf, "200") != NULL)
		printf("the servers return 200 ok\r\n");

	return 0;

}


程序源码百分之九十来自这里 github :https://github.com/kyhkl/hivisoion_projcet.git

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值