HP Socket HttpServer使用

使用HP搭建Socket HttpServer,并且实现post,get,以及websocket,主要是webssockt折腾了不少时间。

首先要自己实现底层接口,都是纯虚函数,需要自己去实现,继承自IHttpServerListener

#pragma once

#include "SocketInterface.h"
#include "stdio.h"
#include  
#include "BASE64.h"
#include "USER_SHA1.h"


#define html_base_path  "f:\\Desktop\\桌面文件整理\\临时工程\\helsinki-blue\\"

/************************************************************************
名称:IComplexHttp 组件监听器基接口
描述:定义 IComplexHttp 组件监听器的所有事件
************************************************************************/
class  HttpServerListernet : public IHttpServerListener
{


	/**********************************************************************/
	/* Give a client a 404 not found status message. */
	/**********************************************************************/
	void not_found(IHttpServer* pSender, CONNID dwConnID)
	{
		const char *pErrorNotFound =
			"Not Found\r\n"\
			"

The server could not fulfill\r\n"\ "your request because the resource specified\r\n"\ "is unavailable or nonexistent.\r\n"\ "\r\n"; pSender->SendResponse(dwConnID, HSC_OK, nullptr, nullptr, 0, (BYTE *)pErrorNotFound, sizeof(pErrorNotFound)); } public: /* * 名称:开始解析通知 * 描述:开始解析 HTTP 报文时,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ EnHttpParseResult OnMessageBegin(IHttpServer* pSender, CONNID dwConnID) { return HPR_OK; } /* * 名称:请求行解析完成通知(仅用于 HTTP 服务端) * 描述:请求行解析完成后,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * lpszMethod -- 请求方法名 * lpszUrl -- 请求行中的 URL 域 * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ //过滤器在此完成 EnHttpParseResult OnRequestLine(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszMethod, LPCSTR lpszUrl) { char buff[512 + 4]; char UrlData[1024 + 4]; char *pParameter = nullptr; //参数 char ExtenName[4]; char path[512]; int len; struct stat st; if (lpszMethod != nullptr) { if (strcmp(lpszMethod, "POST") == 0) //POST { //pSender->SendResponse(dwConnID, HSC_OK, nullptr, nullptr, 0, nullptr); return HPR_OK; } else if (strcmp(lpszMethod, "GET") == 0) //GET { len = strlen(lpszUrl); if (len > 1024) //限制长度为1KB { len = 1024; } if (len > 0) { //拷贝数据到缓冲区中 memcpy(UrlData, lpszUrl, len); UrlData[len] = 0; if (lpszUrl[len - 1] == '/') //当前请求的是目录,打开默认文件 { if (strcmp(UrlData, "/websocket/data/") == 0) //websocket api接口 { //pSender->Send(dwConnID, (BYTE *)"123456\r\n", 8, 0); //pSender->SendWSMessage(dwConnID, true, 0, 0, nullptr, (BYTE *)"123456\r\n", 8, 0); return HPR_OK; } else { sprintf_s(path, 512, "%s%s", html_base_path, "index.html"); } } else //非目录,先处理参数,去掉参数后判断是文件还是虚拟路径URL { pParameter = strstr(UrlData, "?"); //搜索到第一个问号,问号后面的都是参数 if (pParameter != nullptr) //有参数 { *pParameter = '\0'; //截断数据-前面的是URL,后面的是参数,并且去掉了第一个问号 pParameter += 1; //跳过问号 } sprintf_s(path, 512, "%s%s", html_base_path, UrlData); //生成文件绝对路径 } if (stat(path, &st) == -1) //文件不存在 { not_found(pSender, dwConnID); //返回404 } else //文件存在 { pSender->SendLocalFile(dwConnID, path, HSC_OK, nullptr, nullptr, 0);//返回文件 } } return HPR_OK; } } return HPR_ERROR; } /* * 名称:BODY 报文通知 * 描述:每当接收到 HTTP BODY 报文,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * pData -- 数据缓冲区 * iLength -- 数据长度 * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ //收到POST请求负载 EnHttpParseResult OnBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength) { //pSender->Send(dwConnID, (BYTE *)"123456\r\n", 8, 0); pSender->SendResponse(dwConnID, HSC_OK, nullptr, nullptr, 0, pData, iLength); //pSender->SendLocalFile(dwConnID, "f:\\Desktop\\桌面文件夹整理\\青岛站点4.png", HSC_OK, nullptr, nullptr, 0); return HPR_OK; } /* * 名称:状态行解析完成通知(仅用于 HTTP 客户端) * 描述:状态行解析完成后,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * usStatusCode -- HTTP 状态码 * lpszDesc -- 状态描述 * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ EnHttpParseResult OnStatusLine(IHttpServer* pSender, CONNID dwConnID, USHORT usStatusCode, LPCSTR lpszDesc) { return HPR_OK; } /* * 名称:请求头通知 * 描述:每当解析完成一个请求头后,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * lpszName -- 请求头名称 * lpszValue -- 请求头值 * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ EnHttpParseResult OnHeader(IHttpServer* pSender, CONNID dwConnID, LPCSTR lpszName, LPCSTR lpszValue) { if (strcmp("Sec-WebSocket-Key", lpszName) == 0) //收到websocket握手 { THeader lpHeaders[4]; BYTE OutSHA1Buf[512]; static char key[256]; lpHeaders[0].name = "Upgrade"; lpHeaders[0].value = "websocket"; lpHeaders[1].name = "Connection"; lpHeaders[1].value = "Upgrade"; lpHeaders[2].name = "Sec-WebSocket-Accept"; sprintf_s(key, 255, "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", lpszValue); int len = SHA1_String((unsigned char*)key, strlen(key), OutSHA1Buf); base64_encode(OutSHA1Buf, 20, key); lpHeaders[2].value = key; //生成握手加密key lpHeaders[3].name = "Sec-WebSocket-Protocol"; lpHeaders[3].value = "chat"; pSender->SendResponse(dwConnID, HSC_SWITCHING_PROTOCOLS, nullptr, lpHeaders, 3, nullptr, 0); return HPR_OK; } return HPR_OK; } /* * 名称:请求头完成通知 * 描述:解析完成所有请求头后,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * 返回值: HPR_OK -- 继续执行 * HPR_SKIP_BODY -- 跳过当前请求的 HTTP BODY * HPR_UPGRADE -- 升级协议 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ EnHttpParseResult OnHeadersComplete(IHttpServer* pSender, CONNID dwConnID) { return HPR_OK; } /* * 名称:Chunked 报文头通知 * 描述:每当解析出一个 Chunked 报文头,向监听器发送该通知THeader lpHeaders[4]; lpHeaders[0].name = "Upgrade"; lpHeaders[0].value = "websocket"; lpHeaders[1].name = "Connection"; lpHeaders[1].value = "Upgrade"; lpHeaders[2].name = "Sec-WebSocket-Accept"; lpHeaders[2].value = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="; //生成握手加密key lpHeaders[3].name = "Sec-WebSocket-Protocol"; lpHeaders[3].value = "chat"; pSender->SendResponse(dwConnID, HSC_SWITCHING_PROTOCOLS, nullptr, lpHeaders, 4, nullptr, 0); * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * iLength -- Chunked 报文体数据长度 * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ EnHttpParseResult OnChunkHeader(IHttpServer* pSender, CONNID dwConnID, int iLength) { return HPR_OK; } /* * 名称:Chunked 报文结束通知 * 描述:每当解析完一个 Chunked 报文,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ EnHttpParseResult OnChunkComplete(IHttpServer* pSender, CONNID dwConnID) { return HPR_OK; } /* * 名称:完成解析通知 * 描述:每当解析完成一个完整 HTTP 报文,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnParserError() 和 OnClose() 事件并关闭连接 */ EnHttpParseResult OnMessageComplete(IHttpServer* pSender, CONNID dwConnID) { //pSender->Send(dwConnID, (BYTE *)"123456\r\n", 8, 0); //pSender->SendSmallFile(dwConnID, L"f:\\Desktop\\桌面文件夹整理\\新建文本文档 (3).html", nullptr, nullptr); return HPR_OK; } /* * 名称:升级协议通知 * 描述:当需要升级协议时,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * enUpgradeType -- 协议类型 * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnClose() 事件并关闭连接 */ EnHttpParseResult OnUpgrade(IHttpServer* pSender, CONNID dwConnID, EnHttpUpgradeType enUpgradeType) { return HPR_OK; } /* * 名称:解析错误通知 * 描述:当解析 HTTP 报文错误时,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * iErrorCode -- 错误代码 * lpszErrorDesc -- 错误描述 * 返回值: HPR_OK -- 继续执行 * HPR_ERROR -- 引发 OnClose() 事件并关闭连接 */ EnHttpParseResult OnParseError(IHttpServer* pSender, CONNID dwConnID, int iErrorCode, LPCSTR lpszErrorDesc) { return HPR_OK; } /* * 名称:WebSocket 数据包头通知 * 描述:当解析 WebSocket 数据包头时,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * bFinal -- 是否结束帧 * iReserved -- RSV1/RSV2/RSV3 各 1 位 * iOperationCode -- 操作码:0x0 - 0xF * lpszMask -- 掩码(nullptr 或 4 字节掩码,如果为 nullptr 则没有掩码) * ullBodyLen -- 消息体长度 * 返回值: HR_OK / HR_IGNORE -- 继续执行 * HR_ERROR -- 引发 OnClose() 事件并关闭连接 */ EnHandleResult OnWSMessageHeader(IHttpServer* pSender, CONNID dwConnID, BOOL bFinal, BYTE iReserved, BYTE iOperationCode, const BYTE lpszMask[4], ULONGLONG ullBodyLen) { static char buff[32]; static int cnt = 0; //iOperationCode 0:连接帧;1:文本帧;2:二进制数据;8:关闭;9:ping;10:pong if (iOperationCode == 8) //断开连接 { return HR_ERROR; } int len = sprintf_s(buff, 31, "%d", cnt++); BYTE MaskingKey[] = { 11, 121, 24, 191 }; //注意:服务器发送到从机是不需要掩码 int status = pSender->SendWSMessage(dwConnID, 1, 0, 1, nullptr, (BYTE*)buff, len, len); return HR_OK; } /* * 名称:WebSocket 数据包体通知 * 描述:当接收到 WebSocket 数据包体时,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * pData -- 消息体数据缓冲区 * iLength -- 消息体数据长度 * 返回值: HR_OK / HR_IGNORE -- 继续执行 * HR_ERROR -- 引发 OnClose() 事件并关闭连接 */ EnHandleResult OnWSMessageBody(IHttpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength) { /*char buff[32]; static int cnt = 0; int len = sprintf_s(buff, 31, "%d", cnt++); BYTE MaskingKey[] = {11,121,24,191}; int status = pSender->SendWSMessage(dwConnID, false, 0, 2, MaskingKey, (BYTE*)buff, len, len);*/ return HR_OK; } /* * 名称:WebSocket 数据包完成通知 * 描述:当完整接收一个 WebSocket 数据包时,向监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * 返回值: HR_OK / HR_IGNORE -- 继续执行 * HR_ERROR -- 引发 OnClose() 事件并关闭连接 */ EnHandleResult OnWSMessageComplete(IHttpServer* pSender, CONNID dwConnID) { return HR_OK; } /* * 名称:准备监听通知 * 描述:通信服务端组件启动时,在监听 Socket 创建完成并开始执行监听前,Socket 监听 * 器将收到该通知,监听器可以在通知处理方法中执行 Socket 选项设置等额外工作 * * 参数: pSender -- 事件源对象 * soListen -- 监听 Socket * 返回值: HR_OK / HR_IGNORE -- 继续执行 * HR_ERROR -- 终止启动通信服务组件 */ EnHandleResult OnPrepareListen(ITcpServer* pSender, SOCKET soListen) { return HR_OK; } /* * 名称:接收连接通知 * 描述:接收到客户端连接请求时,Socket 监听器将收到该通知,监听器可以在通知处理方 * 法中执行 Socket 选项设置或拒绝客户端连接等额外工作 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * soClient -- TCP: 客户端 Socket 句柄,UDP: 客户端 Socket SOCKADDR 指针 * 返回值: HR_OK / HR_IGNORE -- 接受连接 * HR_ERROR -- 拒绝连接 */ EnHandleResult OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient) { return HR_OK; } /* * 名称:握手完成通知 * 描述:连接完成握手时,Socket 监听器将收到该通知,监听器接收到该通知后才能开始 * 数据收发操作 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * 返回值: HR_OK / HR_IGNORE -- 继续执行 * HR_ERROR -- 引发 OnClose() 事件并关闭连接 */ EnHandleResult OnHandShake(ITcpServer* pSender, CONNID dwConnID) { return HR_OK; } /* * 名称:已发送数据通知 * 描述:成功发送数据后,Socket 监听器将收到该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * pData -- 已发送数据缓冲区 * iLength -- 已发送数据长度 * 返回值: HR_OK / HR_IGNORE -- 继续执行 * HR_ERROR -- 该通知不允许返回 HR_ERROR(调试模式下引发断言错误) */ EnHandleResult OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength) { return HR_OK; } /* * 名称:数据到达通知(PUSH 模型) * 描述:对于 PUSH 模型的 Socket 通信组件,成功接收数据后将向 Socket 监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * pData -- 已接收数据缓冲区 * iLength -- 已接收数据长度 * 返回值: HR_OK / HR_IGNORE -- 继续执行 * HR_ERROR -- 引发 OnClose() 事件并关闭连接 */ EnHandleResult OnReceive(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength) { return HR_OK; } /* * 名称:数据到达通知(PULL 模型) * 描述:对于 PULL 模型的 Socket 通信组件,成功接收数据后将向 Socket 监听器发送该通知 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * iLength -- 已接收数据长度 * 返回值: HR_OK / HR_IGNORE -- 继续执行 * HR_ERROR -- 引发 OnClose() 事件并关闭连接 */ EnHandleResult OnReceive(ITcpServer* pSender, CONNID dwConnID, int iLength) { return HR_OK; } /* * 名称:通信错误通知 * 描述:通信发生错误后,Socket 监听器将收到该通知,并关闭连接 * * 参数: pSender -- 事件源对象 * dwConnID -- 连接 ID * enOperation -- Socket 操作类型 * iErrorCode -- 错误代码 * 返回值: 忽略返回值 */ EnHandleResult OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode) { return HR_OK; } /* * 名称:关闭通信组件通知 * 描述:通信组件关闭时,Socket 监听器将收到该通知 * * 参数: pSender -- 事件源对象 * 返回值:忽略返回值 */ EnHandleResult OnShutdown(ITcpServer* pSender) { return HR_OK; } public: ~HttpServerListernet() {} };

做websocket握手时需要使用到SHA1与BASE64,这2个都是网上找的。

//USER_SHA1.cpp

#include "StdAfx.h"
#include "USER_SHA1.h"
#include "string.h"


typedef struct SHAstate_st
{
	unsigned long h[SHA1_SIZE_BYTE / 4]; /* 存放摘要结果(32*5=160 bits)*/
	unsigned long Nl;
	unsigned long Nh;       /*存放信息总位数,Nh:高32位,Nl:低32位*/
	unsigned long data[16]; /*数据从第0个的高8位开始依次放置*/
	int FlagInWord;     /*标识一个data元素中占用的字节数(从高->低),取值0,1,2,3*/
	int msgIndex;       /*当前已填充满的data数组元素数。*/
	int isTooMang;      /*正常为0,当处理的信息超过2^64 bits时为1;*/
} SHA1_Context;

#define INIT_DATA_h0 0x67452301U
#define INIT_DATA_h1 0xEFCDAB89U
#define INIT_DATA_h2 0x98BADCFEU
#define INIT_DATA_h3 0x10325476U
#define INIT_DATA_h4 0xC3D2E1F0U

#define SHA1CircularShift(bits, word) (((word) << (bits)) | ((word) >> (32 - (bits))))

const unsigned long SHA1_Kt[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
typedef unsigned long(*SHA1_pFun)(unsigned long b, unsigned long c, unsigned long d);

/*定义四个函数*/
static unsigned long SHA1_ft0_19(unsigned long b, unsigned long c, unsigned long d)
{
	return (b&c) | ((~b)&d);
}

static unsigned long SHA1_ft20_39(unsigned long b, unsigned long c, unsigned long d)
{
	return b ^ c ^ d;
}

static unsigned long SHA1_ft40_59(unsigned long b, unsigned long c, unsigned long d)
{
	return (b&c) | (b&d) | (c&d);
}

static unsigned long SHA1_ft60_79(unsigned long b, unsigned long c, unsigned long d)
{
	return b ^ c ^ d;
}

SHA1_pFun ft[] = { SHA1_ft0_19, SHA1_ft20_39, SHA1_ft40_59, SHA1_ft60_79 };

static int SHA1_Init(SHA1_Context *c)
{
	if (NULL == c)
	{
		return -1;
	}

	c->h[0] = INIT_DATA_h0;

	c->h[1] = INIT_DATA_h1;
	c->h[2] = INIT_DATA_h2;
	c->h[3] = INIT_DATA_h3;
	c->h[4] = INIT_DATA_h4;
	c->Nl = 0;
	c->Nh = 0;
	c->FlagInWord = 0;
	c->msgIndex = 0;
	c->isTooMang = 0;
	memset(c->data, 0, 64);

	return 1;
}

int SHA1_GetMsgBits(SHA1_Context *c)
{
	int a = 0;

	if ((NULL == c) || (0 != c->isTooMang))
	{
		return -1;
	}

	a = sizeof(unsigned long) * 8 * c->msgIndex + 8 * c->FlagInWord;

	return a;
}

int SHA1_Clear_data(SHA1_Context *c)
{
	if (NULL == c)
	{
		return -1;
	}

	memset(c->data, 0, 64);

	c->msgIndex = 0;

	c->FlagInWord = 0;

	return 1;
}

int SHA1_One(SHA1_Context *c)
{
	unsigned long AE[5];
	unsigned long w[80];
	unsigned long temp = 0;
	int t = 0;

	if ((NULL == c) || (0 != c->isTooMang))
	{
		return -1;
	}

	for (t = 0; t < 16; ++t)
	{
		w[t] = c->data[t];
	}

	for (t = 16; t < 80; ++t)
	{
		w[t] = SHA1CircularShift(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
	}

	for (t = 0; t < 5; ++t)
	{
		AE[t] = c->h[t];
	}

	for (t = 0; t <= 79; ++t)
	{
		temp = SHA1CircularShift(5, AE[0]) + (*ft[t / 20])(AE[1], AE[2], AE[3]) + AE[4] + w[t] + SHA1_Kt[t / 20];
		AE[4] = AE[3];
		AE[3] = AE[2];
		AE[2] = SHA1CircularShift(30, AE[1]);
		AE[1] = AE[0];
		AE[0] = temp;
	}

	for (t = 0; t < 5; ++t)
	{
		c->h[t] += AE[t];
	}

	SHA1_Clear_data(c);

	return 1;
}

int SHA1_PadMessage(SHA1_Context *c)
{
	int msgBits = -1;

	if ((NULL == c) || (0 != c->isTooMang))
	{
		return -1;
	}

	msgBits = SHA1_GetMsgBits(c);

	if (440 < msgBits)
	{
		c->data[c->msgIndex++] |= (1 << (8 * (4 - c->FlagInWord) - 1));
		c->FlagInWord = 0;

		while (c->msgIndex < 16)
		{
			c->data[c->msgIndex++] = 0;
		}

		SHA1_One(c);

		while (c->msgIndex < 14)
		{
			c->data[c->msgIndex++] = 0;
		}

	}
	else
	{
		c->data[c->msgIndex++] |= (1 << (8 * (4 - c->FlagInWord) - 1));
		c->FlagInWord = 0;

		while (c->msgIndex < 14)
		{
			c->data[c->msgIndex++] = 0;
		}
	}

	while (c->msgIndex < 14)
	{
		c->data[c->msgIndex++] = 0;
	}

	c->data[c->msgIndex++] = c->Nh;

	c->data[c->msgIndex++] = c->Nl;

	return 1;
}

static int SHA1_Update(SHA1_Context *c, const unsigned char *chBuff, unsigned int n)
{
	unsigned int lastBytes = 0;
	unsigned int temp = 0;
	unsigned int i = 0;
	unsigned int tempBits = 0;

	if (!c || !chBuff || !n || c->isTooMang)
	{
		return -1;
	}

	if (n > strlen((char *)chBuff))
	{
		n = strlen((char *)chBuff);
	}

	if (c->FlagInWord > 0)
	{
		temp = (unsigned int)(4 - c->FlagInWord) < n ? (unsigned int)(4 - c->FlagInWord) : n;

		for (i = temp; i > 0; --i)
		{
			c->data[c->msgIndex] |= ((unsigned long)chBuff[temp - i]) << (3 - c->FlagInWord++) * 8;
		}

		tempBits = c->Nl;

		c->Nl += 8 * temp;

		if (tempBits > c->Nl)
		{
			++(c->Nh);

			if (c->Nh == 0)
			{
				c->isTooMang = 1;
			}
		}

		if ((c->FlagInWord) / 4 > 0)
		{
			++(c->msgIndex);
		}

		c->FlagInWord = c->FlagInWord % 4;

		if (c->msgIndex == 16)
		{
			SHA1_One(c);
		}
	}

	chBuff += temp;

	n -= temp;

	if (n >= 4)
	{
		for (i = 0; i <= n - 4; i += 4)
		{
			c->data[c->msgIndex] |= ((unsigned long)chBuff[i]) << 24;
			c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 1]) << 16;
			c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 2]) << 8;
			c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 3]);
			++(c->msgIndex);

			tempBits = c->Nl;
			c->Nl += 32;

			if (tempBits > c->Nl)
			{
				c->Nh++;

				if (c->Nh == 0)
				{
					c->isTooMang = 1;
				}
			}

			if (c->msgIndex == 16)
			{
				SHA1_One(c);
			}
		}
	}

	if (n > 0 && n % 4 != 0)
	{
		lastBytes = n - i;

		switch (lastBytes)
		{

			case 3:
				c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 2]) << 8;

			case 2:
				c->data[c->msgIndex] |= ((unsigned long)chBuff[i + 1]) << 16;

			case 1:
				c->data[c->msgIndex] |= ((unsigned long)chBuff[i]) << 24;
		}

		c->FlagInWord = lastBytes;

		tempBits = c->Nl;
		c->Nl += 8 * lastBytes;

		if (tempBits > c->Nl)
		{
			++(c->Nh);

			if (0 == c->Nh)
			{
				c->isTooMang = 1;
			}
		}

		if (16 == c->msgIndex)
		{
			SHA1_One(c);
		}
	}

	return 1;
}

static int SHA1_Final(SHA1_Context *c, unsigned char * md)
{
	int i = 0;

	if ((NULL == md) || (NULL == c) || (c->isTooMang))
	{
		return -1;
	}

	SHA1_PadMessage(c);

	SHA1_One(c);

	for (i = 0; i < 5; ++i)
	{
		md[4 * i] = (unsigned char)((c->h[i] & 0xff000000) >> 24);
		md[4 * i + 1] = (unsigned char)((c->h[i] & 0x00ff0000) >> 16);
		md[4 * i + 2] = (unsigned char)((c->h[i] & 0x0000ff00) >> 8);
		md[4 * i + 3] = (unsigned char)(c->h[i] & 0x000000ff);
	}

	return 1;
}

int SHA1_String(const unsigned char* inputString, unsigned long len, unsigned char* pOutSHA1Buf)
{
	int rt = -1;
	SHA1_Context c;

	if ((NULL == inputString) || (NULL == pOutSHA1Buf))
	{
		return -1;
	}

	rt = SHA1_Init(&c);

	if (-1 == rt)
	{
		return -1;
	}

	SHA1_Update(&c, inputString, len);

	SHA1_Final(&c, pOutSHA1Buf);
	SHA1_Clear_data(&c);
	return 1;
}


int SHA1_String_Compare(const unsigned char* inputString, unsigned long len, const unsigned char* pOutSHA1Buf)
{
	unsigned char buff[SHA1_SIZE_BYTE] = { 0 };
	int rt = -1;
	int i = 0;

	rt = SHA1_String(inputString, len, buff);

	if (1 == rt)
	{
		for (i = 0; i < SHA1_SIZE_BYTE; ++i)
		{
			if (buff[i] != pOutSHA1Buf[i])
			{
				return -1;
			}
		}

		return 1;
	}
	else
	{
		return -1;
	}
}

int SHA1_File(const char* filePath, unsigned char *buff)
{
	int rt = -1;
	FILE *file = NULL;
	SHA1_Context context;
	int len = 0;
	unsigned char buffer[0x0400] = { 0 };

	file = fopen(filePath, "rb");

	if (NULL == file)
	{
		return -1;
	}
	else
	{
		rt = SHA1_Init(&context);

		if (-1 == rt)
		{
			fclose(file);

			return -1;
		}

		while (len = fread(buffer, 1, 1024, file))
		{
			rt = SHA1_Update(&context, buffer, len);

			if (-1 == rt)
			{
				fclose(file);

				return -1;
			}
		}

		rt = SHA1_Final(&context, buff);

		fclose(file);

		return rt;
	}
}

int SHA1_File_Compare(const char* filePathA, const char *filePathB)
{
	char hashValueA[SHA1_SIZE_BYTE] = { 0 };
	char hashValueB[SHA1_SIZE_BYTE] = { 1 };
	int rt = -1;
	int i = 0;

	if ((NULL == filePathA) || (NULL == filePathB))
	{
		return -1;
	}

	rt = SHA1_File(filePathA, (unsigned char *)hashValueA);

	if (1 == rt)
	{
		rt = SHA1_File(filePathB, (unsigned char *)hashValueB);

		if (1 == rt)
		{
			for (i = 0; i < SHA1_SIZE_BYTE; ++i)
			{
				if (hashValueA[i] != hashValueB[i])
				{
					return -1;
				}
			}

			return 1;
		}
		else
		{
			return -1;
		}
	}
	else
	{
		return -1;
	}
}


/**
* @file SHA1.h
* @brief SHA-1 coden take from gnupg 1.3.92.
* @author Don
* @date 2011-7-28 22:49:55
* @version
* 
copyright: 
*
email: [email protected]
*
company:
* 
All rights reserved.
*
modification:
*
Write modifications here.
*/ #ifndef _USER_SHA1_H #define _USER_SHA1_H #include #include #define SHA1_SIZE_BYTE 20 /** * @brief SHA1_String * * Detailed description. * @param[in] inputString 要进行处理的无符号字符串指针 * @param[in] len 要处理的信息长度,n<= strlen(p); * @param[out] pOutSHA1Buf 输出摘要信息,长度为20的 unsigned char ,共160 bits * @return int */ int SHA1_String(const unsigned char* inputString, unsigned long len, unsigned char* pOutSHA1Buf); /** * @brief SHA1_String_Compare * * Detailed description. * @param[in] inputString * @param[in] len * @param[in] pOutSHA1Buf * @return int */ int SHA1_String_Compare(const unsigned char* inputString, unsigned long len, const unsigned char* pOutSHA1Buf); /** * @brief SHA1_File * * Detailed description. * @param[in] filePath 要计算MD5的文件的路径 * @param[in] buff 输出的MD5值,该缓冲区大小应为MD5_SIZE_BYTE * @return int */ int SHA1_File(const char* filePath, unsigned char* buff); /** * @brief SHA1_File_Compare * * Detailed description. * @param[in] filePathA 要对比MD5的第一个文件的路径 * @param[in] filePathB 要对比MD5的第二个文件的路径 * @return int */ int SHA1_File_Compare(const char* filePathA, const char* filePathB); #endif /**< _USER_SHA1_H */

//BASE64.c

#include "StdAfx.h"
#include "base64.h"
#include 
#include 

// 全局常量定义
const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const char padding_char = '=';

/*编码代码
* const unsigned char * sourcedata, 源数组
* char * base64 ,码字保存
*/
int base64_encode(const unsigned char * sourcedata, unsigned int datalength, char * base64)
{
	int i = 0, j = 0;
	unsigned char trans_index = 0;    // 索引是8位,但是高两位都为0
	//const int datalength = strlen((const char*)sourcedata);
	for (; i < datalength; i += 3){
		// 每三个一组,进行编码
		// 要编码的数字的第一个
		trans_index = ((sourcedata[i] >> 2) & 0x3f);
		base64[j++] = base64char[(int)trans_index];
		// 第二个
		trans_index = ((sourcedata[i] << 4) & 0x30);
		if (i + 1 < datalength){
			trans_index |= ((sourcedata[i + 1] >> 4) & 0x0f);
			base64[j++] = base64char[(int)trans_index];
		}
		else{
			base64[j++] = base64char[(int)trans_index];

			base64[j++] = padding_char;

			base64[j++] = padding_char;

			break;   // 超出总长度,可以直接break
		}
		// 第三个
		trans_index = ((sourcedata[i + 1] << 2) & 0x3c);
		if (i + 2 < datalength){ // 有的话需要编码2个
			trans_index |= ((sourcedata[i + 2] >> 6) & 0x03);
			base64[j++] = base64char[(int)trans_index];

			trans_index = sourcedata[i + 2] & 0x3f;
			base64[j++] = base64char[(int)trans_index];
		}
		else{
			base64[j++] = base64char[(int)trans_index];

			base64[j++] = padding_char;

			break;
		}
	}

	base64[j] = '\0';

	return 0;
}


/** 在字符串中查询特定字符位置索引
* const char *str ,字符串
* char c,要查找的字符
*/
inline int num_strchr(const char *str, char c) // 
{
	const char *pindex = strchr(str, c);
	if (NULL == pindex){
		return -1;
	}
	return pindex - str;
}
/* 解码
* const char * base64 码字
* unsigned char * dedata, 解码恢复的数据
*/
int base64_decode(const char * base64, unsigned char * dedata)
{
	int i = 0, j = 0;
	int trans[4] = { 0, 0, 0, 0 };
	for (; base64[i] != '\0'; i += 4){
		// 每四个一组,译码成三个字符
		trans[0] = num_strchr(base64char, base64[i]);
		trans[1] = num_strchr(base64char, base64[i + 1]);
		// 1/3
		dedata[j++] = ((trans[0] << 2) & 0xfc) | ((trans[1] >> 4) & 0x03);

		if (base64[i + 2] == '='){
			continue;
		}
		else{
			trans[2] = num_strchr(base64char, base64[i + 2]);
		}
		// 2/3
		dedata[j++] = ((trans[1] << 4) & 0xf0) | ((trans[2] >> 2) & 0x0f);

		if (base64[i + 3] == '='){
			continue;
		}
		else{
			trans[3] = num_strchr(base64char, base64[i + 3]);
		}

		// 3/3
		dedata[j++] = ((trans[2] << 6) & 0xc0) | (trans[3] & 0x3f);
	}

	dedata[j] = '\0';

	return 0;
}

//BASE64.h

#ifndef base64_h
#define base64_h



int base64_encode(const unsigned char * sourcedata, unsigned int datalength, char * base64);

#endif /* base64_h */

//测试

IHttpServer *mHttpServer;
HttpServerListernet *mHttpServerListernet;

this->mHttpServerListernet = new HttpServerListernet();
			this->mHttpServer = HP_Create_HttpServer(this->mHttpServerListernet);
			if (this->mHttpServer != nullptr)
			{
				
				if (this->mHttpServer->Start(L"0.0.0.0", 4567) == FALSE)
				{
					int error = this->mHttpServer->GetLastError();
					System::Windows::Forms::MessageBox::Show("初始化web服务器失败,错误代码:" + error, "错误", System::Windows::Forms::MessageBoxButtons::OK,
						System::Windows::Forms::MessageBoxIcon::Error);

				}
			}
			else
			{
				System::Windows::Forms::MessageBox::Show("初始化 mHttpServer 失败!", "错误", System::Windows::Forms::MessageBoxButtons::OK,
					System::Windows::Forms::MessageBoxIcon::Error);
			}

html_base_path:web网页目录,默认打开里面的index.html文件

 

你可能感兴趣的:(VC++,.NET)