⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httprequest.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 2 页
字号:
void HttpRequest::MakeHeadMsg(BOOL post, LPTSTR buf)
{
	LPTSTR start = buf;
	if(post)
	{
		_tcscpy(start, _defaultContentType);
		start += _tcslen(_defaultContentType);
	}
	if(h_File != NULL)
	{
		if(m_dwOffset != UINT_MAX)
		{
			_tcscpy(start, _T("\r\n"));
			if(m_dwOffsetEnd != UINT_MAX)
				_stprintf(start, _T("Range: bytes= %d-%d"), m_dwOffset, m_dwOffsetEnd);
			else
				_stprintf(start, _T("Range: bytes= %d-"), m_dwOffset);
		}
	}
}

BOOL HttpRequest::OpenRequest(LPCWSTR url, BOOL cache, LPCWSTR send)
{
	
#ifdef _UNICODE
	LPCWSTR purl = url;
#else
	char* purl = new char[2048];
	WideCharToMultiByte(CP_ACP, 0, url, -1, purl, 2048, NULL, NULL);
#endif

	size_t size = 0;
	if(send != NULL)
		size = wcslen(send) * sizeof(WCHAR);
	LPVOID pdata = (LPVOID) send;
	if(fWide == FALSE && send != NULL)
	{
		pdata = (LPVOID) new char[size];
		WideCharToMultiByte(CP_ACP, 0, send, -1, (char*) pdata, size, NULL, NULL);
		size = strlen((char*) pdata);
	}

	BOOL ret;
	ret = OpenRequestEx(purl, cache, pdata, size);

#ifndef _UNICODE
	delete[] purl;
#endif
	if(fWide == FALSE && send != NULL)
		delete[] pdata;
	return ret;
}

BOOL HttpRequest::OpenRequest(LPCSTR url, BOOL cache, LPCSTR send)
{
#ifndef _UNICODE
	LPCSTR purl = url;
#else
	WCHAR* purl = new WCHAR[2048];
	MultiByteToWideChar(CP_ACP, 0, url, -1, purl, 2048);
#endif

	DWORD size = 0;
	if(send != NULL)
		size = strlen(send);
	LPVOID pdata = (LPVOID) send;
	if(fWide != FALSE && send != NULL)
	{
		pdata = (LPVOID) new WCHAR[size];
		MultiByteToWideChar(CP_ACP, 0, send, -1, (WCHAR*) pdata, size);
		size = wcslen((WCHAR*) pdata)*sizeof(WCHAR);
	}

	BOOL ret;
	ret = OpenRequestEx(purl, cache, pdata, size);

#ifdef _UNICODE
	delete[] purl;
#endif
	if(fWide != FALSE && send != NULL)
		delete[] pdata;
	return ret;
}

BOOL HttpRequest::OpenRequestEx(LPCTSTR url, BOOL cache, const void* send, DWORD sendsize)
{
	HANDLE hSemaphore = ::OpenSemaphore(SEMAPHORE_ALL_ACCESS | SEMAPHORE_MODIFY_STATE | SYNCHRONIZE
		, NULL, HTTP_REQUEST_LIMIT_NAME);

	BOOL funOK = FALSE;
	HINTERNET HSO = NULL; 
	HINTERNET HIO = NULL;
	HINTERNET HQO = NULL;
	TCHAR*	p_stN = new TCHAR[256];
	TCHAR*	p_flN = new TCHAR[2048];
	TCHAR*	p_bufstr = new TCHAR[1024];
	BYTE*	p_buf = new BYTE[1024];
	DWORD	port = 80;

__try{

	if(!ParseURL(url, p_stN, p_flN, &port))
	{
		errorcode = ERROR_INTERNET_NAME_NOT_RESOLVED;
		__leave;
	}

	if(hSemaphore)
	{
		DWORD ret = ::WaitForSingleObject(hSemaphore, Connect_timeout*2);
		if(ret == WAIT_TIMEOUT)
		{
			errorcode = 12002;
			__leave;
		}
		else if(ret == WAIT_ABANDONED)
		{
			errorcode = USER_STOP;
			__leave;
		}
	}

	DWORD type; LPCTSTR proxystr = NULL;
	switch(b_useproxy)
	{
	case 0: type = INTERNET_OPEN_TYPE_DIRECT;break;
	case 1: type = INTERNET_OPEN_TYPE_PRECONFIG;break;
	case 2: type = INTERNET_OPEN_TYPE_PROXY;
		proxystr = m_proxystr;
		break;
	default: type = INTERNET_OPEN_TYPE_PRECONFIG;break;
	}
	HSO = ::InternetOpen(INTERNET_CONNECT_ADAGENT, type, proxystr, NULL, INTERNET_FLAG_ASYNC);
	if(HSO == NULL)
	{
		errorcode = GetLastError();
		__leave;
	}

	if(::InternetSetStatusCallback(HSO, AsyncInternetCallback) == INTERNET_INVALID_STATUS_CALLBACK)
	{
		errorcode = GetLastError();
		__leave;
	}


	HDResetEvent();
	HIO = InternetConnect(HSO, p_stN, (WORD) port , NULL,NULL,
            INTERNET_SERVICE_HTTP , 0, reinterpret_cast<DWORD>(this));
	if(HIO == NULL)
	{
		if(WaitingEvent(Connect_timeout))
			__leave;
		HIO = m_hInternet;
	}
  
      // 3.初始化下载请求
	const TCHAR AcceptType[] = _T("*/*");
	LPCTSTR p_FA[] = {AcceptType, NULL};
	TCHAR Verb[10];
	if(send != NULL)
		_tcscpy(Verb, _T("POST"));
	else
		_tcscpy(Verb, _T("GET"));

	if(!cache)
		type = INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD;
	else
		type = 0;

	HDResetEvent();

    HQO = HttpOpenRequest(HIO,
            Verb, // 从服务器获取数据
            p_flN, // 想读取的文件的名称
            _T("HTTP/1.1"), // 使用的协议
            NULL,
            p_FA,
            type,
            reinterpret_cast<DWORD>(this));

      // 4.发送下载请求
	*p_bufstr = 0;
	MakeHeadMsg(send != NULL, p_bufstr);
	BOOL ret;
	if(*p_bufstr == 0)
		ret = HttpSendRequest(HQO, NULL, 0, NULL, 0);
	else if(send != NULL)
		ret = HttpSendRequest(HQO, p_bufstr, _tcslen(p_bufstr), (LPVOID) send, sendsize);
	else
		ret = HttpSendRequest(HQO, p_bufstr, _tcslen(p_bufstr), NULL, 0);

    if(!ret)
	{
		if(WaitingEvent(Connect_timeout))
			__leave;
	}

	DWORD length, result;
	result = 32774;	//ERROR_HTML
	length = sizeof(result);
	if(!::HttpQueryInfo(HQO , HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER
		, &result, &length, NULL))
	{
		errorcode = GetLastError();
		__leave;
	}
	if(result != 200 && result != 206)
	{
		errorcode = result;
		__leave;
	}

	result = UINT_MAX;

/*	TCHAR* tbuf = new TCHAR[1024];
	length = 1024;
	::HttpQueryInfo(HQO , HTTP_QUERY_RAW_HEADERS_CRLF , tbuf, &length, NULL);*/

	::HttpQueryInfo(HQO , HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &result, &length, NULL);
	if(result == UINT_MAX)
		result = 1024;
	else
		result += 1; //避免一次无效的扩展缓冲区

	//downloading
	InitWrite(result);

	//**********the internetreadfileexW can't not be used for some reason *************//
	INTERNET_BUFFERSA i_buf = {0};
	i_buf.dwStructSize = sizeof(INTERNET_BUFFERSA);
	i_buf.lpcszHeader = NULL;
	i_buf.dwBufferLength = 1024;
	i_buf.lpvBuffer = p_buf;

	while(1)
	{
		HDResetEvent();
		if (FALSE == ::InternetReadFileExA(HQO , &i_buf, IRF_ASYNC, reinterpret_cast<DWORD>(this)))
		{
			if(WaitingEvent(Request_timeout))
				__leave;
		}
		else
		{
			//在网络传输速度快,步长较小的情况下,
			//InternetReadFileEx 经常会直接返回成功,
			//因此要判断是否发生了用户要求终止子线程事件。
			if (WAIT_OBJECT_0 == ::WaitForSingleObject(m_hEvent[0], 0))
			{
				errorcode = USER_STOP;
				__leave;
			}
		}

		if(i_buf.dwBufferLength == 0)
			break;

		if(!WriteBuffer(p_buf, i_buf.dwBufferLength))
			__leave;

		i_buf.dwBufferLength = 1024;
		i_buf.lpvBuffer = p_buf;
	}

	readstrpos = 0;
	buflength = m_dwOffset;
	funOK = TRUE;
  }
  __finally
  {
	InternetCloseHandleAsync(HQO);
	InternetCloseHandleAsync(HSO);
	if(hSemaphore)
		::ReleaseSemaphore(hSemaphore, 1, NULL);
	delete[] p_stN;
	delete[] p_flN;
	delete[] p_buf;
	delete[] p_bufstr;
  }

  return funOK;
}

BOOL HttpRequest::ParseURL(LPCTSTR src, LPTSTR stN, LPTSTR flN, DWORD* port)
{
   TCHAR* p_src = new TCHAR[4096];
   _tcscpy(p_src, src);
   TCHAR* tmp = _tcsstr(p_src, _T("http://"));

   if(tmp == NULL || (p_src - tmp) != 0)
   {
	   delete[] p_src;
	   return FALSE;
   }

   tmp = _tcschr(p_src + 7, _T('/'));
   if(tmp == NULL)
   {
	   flN[0] = 0;
	   _tcscpy(stN, p_src + 7);
   }
   else
   {
	   *tmp = 0;
	   _tcscpy(stN, p_src + 7);
	   *tmp = _T('/');
	   _tcscpy(flN, tmp);
   }
	tmp = _tcschr(stN, _T(':'));
	if(tmp == NULL)
		*port = 80;
	else
	{
		*tmp = 0;
		*port = _ttoi(tmp + 1);
	}

   delete[] p_src;
   return TRUE;
}

void CALLBACK HttpRequest::AsyncInternetCallback(
		    HINTERNET hInternet,
			DWORD dwContext,
			DWORD dwInternetStatus,
			LPVOID lpvStatusInformation,
			DWORD dwStatusInformationLength)
{
    HttpRequest * pObj = reinterpret_cast<HttpRequest*>(dwContext);

    switch(dwInternetStatus)
    {
    //句柄被创建
    case INTERNET_STATUS_HANDLE_CREATED:
    pObj->m_hInternet = (HINTERNET)(((LPINTERNET_ASYNC_RESULT)
     (lpvStatusInformation))->dwResult);
    break;
   //句柄被关闭
   case INTERNET_STATUS_HANDLE_CLOSING:
	::SetEvent(pObj->m_hEvent[1]);
    break;
   //一个请求完成,比如一次句柄创建的请求,或者一次读数据的请求
   case INTERNET_STATUS_REQUEST_COMPLETE:
	   //如果发生错误,则设置子线程退出事件
     //这里也是一个陷阱,经常会忽视处理这个错误,
	   DWORD ret;
    if (( ret = ((LPINTERNET_ASYNC_RESULT) (lpvStatusInformation))->dwError) != ERROR_SUCCESS)
     	pObj->errorcode = ret;
	else
		pObj->errorcode = 0;
	::SetEvent(pObj->m_hEvent[1]);
    break;
	//连接中断
	case INTERNET_STATUS_CONNECTION_CLOSED:
	   break;
	//重定向连接
	case INTERNET_STATUS_REDIRECT:
	   break;
	//已连接
	case INTERNET_STATUS_CONNECTED_TO_SERVER:
	   break;
	//解析服务器
	case INTERNET_STATUS_RESOLVING_NAME:
		break;
	case INTERNET_STATUS_REQUEST_SENT:
	   break;
   }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -