一个winhttp的服务程序

windows WinHttp WinInet和WinHttp是windows平台下提供了两套独立的网络库,按照微软官方的说法, WinInet的优势在于client-端的应用,而WinHttp更适用于server-端编程。从名称上我们可以看出WinHttp在Http协议应用方面要比WinInet更加专业,WinInet支持的协议包括Gopher\HTTP\HTTPS\FTP较为杂乱,而WinHttp库专门是为HTTP\HTTPS服务的。 在一个Session之上可以存在多个Connection对象,每个Connection对应于一个目 阅读详情

 

    公司的考勤系统有两套,一套是门卡打卡上班,另一套是计算机登陆考勤网站上班。像我这样成天乘公交上班的人,不知道什么时候一堵车就迟到了。因此无聊加无奈,才写了下面的程序。。。。
    首先考察一下门卡系统。因为要刷卡才能上班,刷卡数据保存在公司linux服务器上,没啥手脚可以动。于是转向网站考勤系统。这个网站是用jsp写得,于是打算用EffeTech HTTP Sniffer侦查一下。本来以为需要很费劲的,其实嗅探下来结果非常简单,登陆请求就是用URL rewrite技术包装的。把这个url请求截获之后,就可以开始模拟请求了。用啥语言呢,java中可以直接用socket发请求,但是win32的Platform Sdk中有更高层的HTTP协议包装——winhttp。于是就简单地设计了下面的请求发送类
 
//-----------------------------------------------------------------------
// Name: class CMyWinHttp
// Desc: Connect to the web server, process the interaction based on http
//-----------------------------------------------------------------------
class CMyWinHttp
{
       HINTERNET m_hSession;
       HINTERNET m_hConnect;
       HINTERNET m_hRequest;
 
public:
       CMyWinHttp();
 
       INT Init();
       VOID Close();
       BOOL ProcessOneRequest(LPCWSTR pwszObjectName);
 
};
 
    构造函数就不说了,反正是初始化成员变量为NULL。Init函数比较简单,其中HOST和PORT就是服务器IP和80端口。
///---------------------------------------------------------------
///    DESC: Init the connection
///    Unless the host/port/user-agent changes...
///---------------------------------------------------------------
INT CMyWinHttp::Init()
{
       // Use WinHttpOpen to obtain a session handle.
       m_hSession = WinHttpOpen( USER_AGENT, 
              WINHTTP_ACCESS_TYPE_NO_PROXY,
              WINHTTP_NO_PROXY_NAME,
              WINHTTP_NO_PROXY_BYPASS, 0 );
 
       // Specify an HTTP server.
       if( m_hSession )
              m_hConnect = WinHttpConnect(      m_hSession,
              HOST,
              PORT, 0 );
 
       if ( m_hConnect )
              return 0;
      
       return GetLastError();
}
 
    Close()函数也不说了,关闭一些句柄。对生成和发送Get请求的包装处理如下:
BOOL CMyWinHttp::ProcessOneRequest(LPCWSTR pwszObjectName)
{
       DWORD dwSize          = 0;
       DWORD dwDownloaded           = 0;
       LPSTR pszOutBuffer;
       BOOL bResults         = FALSE;
 
       // Create an HTTP request handle.
       if( m_hConnect )
              m_hRequest = WinHttpOpenRequest(      m_hConnect,
              L"GET",
              pwszObjectName,
              NULL,
              WINHTTP_NO_REFERER,
              WINHTTP_DEFAULT_ACCEPT_TYPES,
              0 );
 
       // Send a request.
       if( m_hRequest )
              bResults = WinHttpSendRequest( m_hRequest,
              ADDITIONAL, -1L,
              WINHTTP_NO_REQUEST_DATA, 0,
              0, 0 );
 
 
       // End the request.
       if( bResults )
              bResults = WinHttpReceiveResponse( m_hRequest, NULL );
 
       // Keep checking for data until there is nothing left.
       if( bResults )
       {
              do
              {
                     // Check for available data.
                     dwSize = 0;
                     if( !WinHttpQueryDataAvailable( m_hRequest, &dwSize ) )
                            printf( "Error %u in WinHttpQueryDataAvailable./n",
                            GetLastError( ) );
 
                     // Allocate space for the buffer.
                     pszOutBuffer = new char[dwSize+1];
                     if( !pszOutBuffer )
                     {
                            printf( "Out of memory/n" );
                            dwSize=0;
                     }
                     else
                     {
                            // Read the data.
                            ZeroMemory( pszOutBuffer, dwSize+1 );
 
                            if( !WinHttpReadData( m_hRequest, (LPVOID)pszOutBuffer,
                                   dwSize, &dwDownloaded ) )
                                   printf( "Error %u in WinHttpReadData./n",
                                   GetLastError( ) );
                            else
                                   printf( "%s", pszOutBuffer );
 
                            // Free the memory allocated to the buffer.
                            delete [] pszOutBuffer;
                     }
              } while( dwSize > 0 );
       }
 
 
       // Report any errors.
       if( !bResults )
              printf( "Error %d has occurred./n", GetLastError( ) );
 
       return bResults;
}
 
    主函数只要这么写就可以了,其中SUBMIT是解析出来的GET请求。
int _tmain(int argc, _TCHAR* argv[])
{
 
       CMyWinHttp* myWinHttp = new CMyWinHttp();
       if ( myWinHttp->Init() != 0 )
              return -1;
 
       if ( !myWinHttp->ProcessOneRequest(SUBMIT) )
              return -1;
 
       myWinHttp->Close();
       return 0;
}
 
    到此九阳神功略有小成,下面要关注的就是怎么让它每天都可以自己跑。可以选择放到计
划任务中,可是总有设置的麻烦。于是打算写个服务,只有在系统开机的时候运行一次,然后
再把机器BIOS设置为定时启动就可以了(俺rp不错,正好机器的BIOS中有这个功能,而且还能
选择autoboot only weekday,晕一个)。网上介绍编写系统服务的铺天盖地,我把那个
NTService修改了一下就可以用了。类设计如下:
//-----------------------------------------------------------------------------
// Name: class CService
// Desc: System service registration
//-----------------------------------------------------------------------------
class CService
{
       DWORD dwAttendantTime;
       TCHAR* lpServiceName;
public:
       CService();
       //~CService();
       static void WINAPI ServiceMain( DWORD argc, TCHAR*      argv[] );
       static void WINAPI ServiceControlHandler( DWORD controlCode );
       void InstallService();
       void UninstallService();
       void RunService();
 
       SERVICE_STATUS serviceStatus;
       SERVICE_STATUS_HANDLE serviceStatusHandle;
       static CService* m_This;
       HANDLE stopServiceEvent;
 
};
    其中有两个静态的成员函数,用来做win32api的回调函数。哎,没有c#的delegate爽。顺便提一下,网上那篇高性能c++委托的实现看起来不太实用,如果不强调高性能的话使用静态成员函数作Callback函数就可以了。注意有一个静态成员指针m_This指向类实例,在回调函数中可以使用它访问类的成员(这个事情在java中是完全不可思议的,因为Java中没有指针,所以Java只能使用内部类的技术来完成图形界面的事件相应)。跑题了,下面回过来看ServiceMain()函数
 
//-----------------------------------------------------------------------------
/// @brief    Static Function ServiceMain for CallBack
/// @note     Entry point of the service
//-----------------------------------------------------------------------------
void CService::ServiceMain( DWORD argc, TCHAR* argv[] )
{
       CService& ThisService = *m_This;
       struct tm* tm;
       time_t now;
       DWORD minnow;
       CMyWinHttp* myWinHttp;
       ThisService.dwAttendantTime = GenerateRandomTime();
       // initialise service status
       ThisService.serviceStatus.dwServiceType = SERVICE_WIN32;
       ThisService.serviceStatus.dwCurrentState = SERVICE_STOPPED;
       ThisService.serviceStatus.dwControlsAccepted = 0;
       ThisService.serviceStatus.dwWin32ExitCode = NO_ERROR;
       ThisService.serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
       ThisService.serviceStatus.dwCheckPoint = 0;
       ThisService.serviceStatus.dwWaitHint = 0;
 
       ThisService.serviceStatusHandle = RegisterServiceCtrlHandler(
              ThisService.lpServiceName,
              ServiceControlHandler );
 
       if ( ThisService.serviceStatusHandle )
       {
              // Service is starting
              ThisService.serviceStatus.dwCurrentState = SERVICE_START_PENDING;
              SetServiceStatus(    ThisService.serviceStatusHandle,
                     &(ThisService.serviceStatus) );
 
              // Do initialization
              ThisService.stopServiceEvent = CreateEvent( 0, FALSE, FALSE, 0);
 
              // Running
              ThisService.serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
              ThisService.serviceStatus.dwCurrentState = SERVICE_RUNNING;
              SetServiceStatus(    ThisService.serviceStatusHandle,
                     &(ThisService.serviceStatus) );
 
              do
              {
                     //Beep( 1000, 100 );
                     //Sleep(100);
                     time(&now);
                     tm = localtime(&now);
                     minnow = tm->tm_min;
                     // only exectue at 8:00~9:00 on weekday
                     if ( (tm->tm_wday == 0) || (tm->tm_wday == 6) || (tm->tm_hour != 8) )
                     {
                            Sleep(2000);
                            SetEvent( ThisService.stopServiceEvent );
                            break;
                     }
                     if (ThisService.dwAttendantTime+38<minnow)
                     {
                            // for example: now is 8:45, min is 26, then do following:
                            myWinHttp = new CMyWinHttp();
                            myWinHttp->Init();
                            myWinHttp->ProcessOneRequest(QIANZ_SUBMIT);
                            myWinHttp->Close();
                            SetEvent( ThisService.stopServiceEvent );
                     }
                     else
                     {
                            Sleep(1000);
                     }
              }
              while ( WaitForSingleObject( ThisService.stopServiceEvent, 1000 ) == WAIT_TIMEOUT );
 
              // Service was stopped
              ThisService.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
              SetServiceStatus(    ThisService.serviceStatusHandle,
                     &(ThisService.serviceStatus) );
 
              // do cleanup here
              CloseHandle( ThisService.stopServiceEvent );
              ThisService.stopServiceEvent = 0;
 
              // service is now stopped
              ThisService.serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
              ThisService.serviceStatus.dwCurrentState = SERVICE_STOPPED;
              SetServiceStatus(    ThisService.serviceStatusHandle,
                     &(ThisService.serviceStatus) );
       }
}
    看明白了吗?使用引用CService& ThisService = *m_This来访问成员变量,并且只
有在早上八点到九点的时候向服务器发送考勤上班请求,然后自动关闭服务。这样以后就不会
迟到了。
WinHTTP中的SSL WinHTTP中的SSLMicrosoft Windows HTTP服务(WinHTTP)支持安全套接字层(SSL)事务,包括客户端证书。 本主题说明SSL事务中涉及的概念以及如何使用WinHTTP处理它们。0x01.安全链路层SSL是确保安全HTTP事务的成熟标准。 SSL提供了一种机制,可对客户端和服务器之间的所有事务执行高达128位的加密。它使客户端能够通过使用服务器证书来验证服务器是否属于可 阅读详情

相关推荐

WinHTTP会话概述

WinHTTP会话概述Microsoft Windows HTTP服务(WinHTTP)公开了一组C / C ++函数,使您的应用程序能够访问Web上的HTTP资源。 本主题概述了如何使用这些函数与HTTP服务器交互。0x01.使用WinHTTP API访问Web下图显示了与HTTP服务器交互时通常调用WinHTTP函数的顺序。 阴影框表示生成HINTERNET句柄的函数,而平面框表示使用这些句柄的

胸怀世界 1593

WINHTTP的API接口说明。

BOOL WINAPI WinHttpAddRequestHeaders(   _In_  HINTERNET hRequest,   _In_  LPCWSTR pwszHeaders,   _In_  DWORD dwHeadersLength,   _In_  DWORD dwModifiers ); 作用:添加一个HTTP的请求头域。 参数说明: hRequest [in]

fengsh998的专栏 4万+

c++调用winhttp对象

Http访问有两种方式,GET和POST,就编程来说GET方式相对简单点,它不用向服务器提交数据,程序中使用POST方式, 提交数据并从服务器获取返回值。 为实现Http访问,微软提供了二套API:WinINet, WinHTTP。WinHTTP比WinINet更加安全和健壮,可以这么认为WinHTTP是WinINet的升级版本。 程序中,通过一个宏的设置来决定是使用WinHttp还

编程论坛 3182

使用WinHttp接口实现HTTP协议Get、Post和文件上传功能

我实现了一个最新版本的接口,详见《实现HTTP协议Get、Post和文件上传功能——使用WinHttp接口实现》。还有基于libcurl实现的版本《实现HTTP协议Get、Post和文件上传功能——使用libcurl接口实现》。以下是原博文: 我们在做项目开发时,往往会涉及到和服务器通信。对于安全性要求不高的情况,一般我们采用HTTP通信协议。对于喜欢挑战底层技术...

方亮的专栏 6万+

使用c++ winhttp实现post请求

winhttp是windows网络库,要测试自己写的post请求是否有效,首先得在postman上面建立一个可用的接口。我的如下。 代码思路如下: 1、首先使用WinHttpCrackUrl拆解链接,后面会使用到拆解出来的信息。 2、再使用WinHttpOpen初始化 3、WinHttpSetTimeouts设置超时,这一步可有可无。 4、WinHttpConnect链接到目标,这里就需要使用拆解出来的信息了 5、WinHttpOpenRequest创...

dzhongjie的博客 5345

c++ winhttp通过https双向认证

不喜欢看下面内容的tx可以直接下载源代码;但是上传到csdn下载哪里,要等很长时间,无法把上传连接放到这里 代码中的ca.p12放到与exe相同目录下,并且应该是自己生产的; 总结: 两个关键点: 1 win下如何加载fpx格式的客户端认证证书,并用于https认证 2 如何通过winhttp进行SSL certificate 主要内容: 一 加载fpx格式证

8020

使用WinHTTP与服务器通讯

WinHTTP 的工作流程如下 一.初始化WinHTTP 在与服务器交互之前, 必须用调用WinHttpOpen进行初始化,WinHttpOpen创建一个会话,并返回该会话的句柄,接着有了这个句柄, WinHttpConnect就能指定一个目标服务器 注意:调用了WinHttpConnect并不意味着和服务器建立了真正的连接 二.打开一个请求 WinHttpOpenReq...

知行合一 3928

C++使用winhttp以POST/GET方法实现报文转发与接收

这里仅仅是我的开发的一点经验, C++通过httppost实现接口信息交互。 目录准备其他情况代码实现包含文件实现代码函数解释调用注意事项 准备 c++调用httppost方法实现报文转发接收之前的准备工作,先通过postman测试接口是否连通。 这里的是地址+端口+接口 后面一定要加上 ?param= 然后看返回的报文是否正确 其他情况 如果电脑没有postman可以用ie浏览器代替,地址+端口+接口 后面一定要加上 ?param= +发送报文,回车查看页面。 代码实现 包含文件 下面 包含的头文件与l

qq_34150669的博客 4683

WinHttp支持HTTPS下载

#include "windows.h" #include "winhttp.h" #include "wchar.h" #pragma comment(lib,"Winhttp.lib") // SSL (Secure Sockets Layer) example // compile for console void main() { HINTERNET hOpen = 0; HINTER

Reverser的专栏 3121

C++ VS winhttp 封装一个下载器

想要用C++下载个网上的东西一般都比较麻烦,大多数人都会选择去使用第三方库。但实际上,windows平台其实已经提供了我们相关的api函数,可以直接在VS中使用,而无需去装其它人写的第三方库,只不过使用起来比较麻烦而已。所以为了简化使用,本文将简单介绍一些这些API的使用方法,并将其封装为一个类,可以直接复制到你的代码中去使用。

余识- 755

Windows平台下的WinHttp类:HTTP通信的全面解决方案

在本章中,我们将介绍Windows平台上的WinHttp类API,它是一套用于发送HTTP请求和接收HTTP响应的组件。WinHttp类API支持多种网络协议,如HTTP和HTTPS,并且设计得足够灵活以满足不同开发者的需求,无论是桌面应用还是企业级应用,它都能提供稳定且高效的网络通信解决方案。在第四章中,我们深入了解了WinHttp类对UNICODE编码的支持及其重要性。UNICODE编码使得WinHttp类可以轻松处理多语言文本,从而提升应用程序的全球适用性。

weixin_28235889的博客 1542

WinHttp应用demo

#include #include #include #pragma comment(lib, "winhttp")struct callback_param_t{HINTERNET hInet;DWORD dwErrCert;};static VOID CALLBACKSyncCallback(HINTERNET, DWORD_PTR, DWORD,

Branze的专栏 2942

Delphi中基于WinHTTP的HTTP通信库解析与应用

Delphi作为一款功能强大的开发工具,提供了丰富的网络通信功能。HTTP通信作为网络开发中的重要组成部分,在Delphi中主要通过WinINet、WinHTTP和indy组件等实现。其中WinHTTP因其稳定性和底层控制能力成为许多开发者偏好的选择。在本章中,我们将从HTTP通信的基本概念出发,逐步介绍Delphi中的HTTP通信方法,包括如何使用WinHTTP API进行网络请求和响应处理,从而为接下来的章节内容打下坚实的基础。

weixin_42577243的博客 880

WinHttp 类封装

头文件 #pragma once #include <Windows.h> #include <stdio.h> #include <string> using std::string; using std::wstring; bool libHttp_Get(wstring wszServerName,WORD nServerPort, wstring w...

ChinaPrc 1052

逆变器专题(9)-基于dq坐标系的逆变器解耦控制建模与实时仿真分析

本文深入探讨了基于dq坐标系的逆变器解耦控制建模与实时仿真分析。通过生动的比喻和详细的数学推导,阐述了如何通过坐标变换和前馈补偿实现d轴与q轴的独立控制,从而提升系统动态性能与稳定性。文章还介绍了在MATLAB/Simulink中搭建仿真模型、分析动态响应与稳定性的方法,并展望了硬件在环(HIL)实时仿真的高级验证手段,为新能源并网与电机驱动领域的工程师提供了宝贵的实践指南。

gold的博客 547

【CV论文精读】【协同感知综述】Collaborative Perception for Autonomous Driving :Current Status and Future Trend

感知是自动驾驶系统的关键模块之一,近年来取得了很大进展。然而,单个车辆的有限能力导致感知性能提高的瓶颈。为了突破个体感知的局限,协作感知被提出,它使车辆能够共享信息来感知视线和视野之外的环境。本文综述了有前途的协作感知技术的相关工作,包括介绍了基本概念,概括了协作模式,总结了协作感知的关键要素和应用。最后,我们讨论了这一研究领域面临的挑战和问题,并给出了一些潜在的进一步方向。

weixin_44184852的博客 4690

使用WinINet和WinHTTP实现Http访问

使用WinINet和WinHTTP实现Http访问 Http访问有两种方式,GET和POST,就编程来说GET方式相对简单点,它不用向服务器提交数据,在这个例程中我使用POST方式,提交数据value1与value2,并从服务器得到他们的和(value1 + value2)。 为实现Http访问,微软提供了二套API:WinINet, WinHTTP。WinHTTP比WinINet更加安全和健

yangshuangtao的专栏 4394

ESP32设备驱动-直流电机与L298N电机驱动器

在本文中,我们将介绍如何使用ESP32通过L298N电机驱动器驱动直流电机。

视觉与物联智能 3595

winhttp demo

#include <string>#include <iostream>#include <windows.h>#include <winhttp.h> #pragma comment(lib,"winhttp.lib")#pragma comment(lib,"user32.lib") void main(){ DWORD dwSi...

dcjvfs0466的博客 243

图解B+树的插入过程

B+ 树在现代数据库中很常见,如果我们了解它,在工作中可能对性能优化会有更好的帮助! 最近我一直在思考 B+ 树的高度是由什么决定的。知道我了解了 B+ 树的插入过程,才有一种恍然大悟的感觉! 网上的一些资料杂乱无章,不同的数据库可能还有对 B+ 树有不同的实现。但是万变不离其宗,B+ 树的定义,大致如下所示: 总结一下,B+ 树有下面 5 个重要的特点。 B+ 树包含 2 种类型的结点: 内部结点(也称索引结点)和叶子结点。 根结点本身即可以是内部结点,也可以是叶子结点。 根结点的关键字个数最

愿君出走半生,归来时仍是少年 2134

2、TrustZone(内含链接)——长期学习内容

ARM系列学习路径整理,希望对大家有用。

HoneyIC的博客 232

MFC使用WinHttp实现Http访问

最近在做MFC和Java搭建的Web平台进行Http通信

u014023993的专栏 7129

RISC-V CPU设计(三)---多周期CPU的设计与实现

基本情况 本多周期CPU支持RV32I指令集(fence,ecall,ebreak除外),已通过部分指令的测试,如代码有bug,欢迎指出。 模块划分 代码将CPU划分为以下几个模块: 1.控制单元:ControlUnit 用于产生控制信号,是CPU的大脑,指挥中枢。 2.分支决策单元:BranchUnit 用于决定B型指令是否发生跳转 3.立即数单元:ImmUnit 用于从指令中解析出立即数. 4.寄存器堆:RegisterFile RISC-V的32个寄存器,其中x0寄存器恒为0,不可更改。 5.指令存储

qq_40268672的博客 5542

WINHTTP的API接口说明

BOOL WINAPI WinHttpAddRequestHeaders( _In_ HINTERNET hRequest, _In_ LPCWSTR pwszHeaders, _In_ DWORD dwHeadersLength, _In_ DWORD dwModifiers ); 作用:添加一个HTTP的请求头域。 参数说明: hRequest [in] 一个HINTERNET句柄通过调用WinHttpOpenRequest返回。 pwszHeaders [in] 请求的头...

玞珺博客 1588

定位分析RCU stall问题

在编译内核时打开或者在启动参数中增加这样统计信息是在采样周期中收集的。其中number行分别是发生stalled的cpu上的硬中断,软中断,和上下文的切换次数cputime行的前三列分别是硬中断,软中断和任务消耗的cpu时间,单位为ms.最后一个数字是统计的周期时间(ms).因为用户态的任务通常不会引起RCU CPU stalls,所以任务通常是内核任务,这也是为什么只统计system cpu的原因.

happyAnger6的专栏 1994

11. 使用 HTTP PUT, PATCH 以及 MERGE 请求消费 SAP ABAP OData 服务修改操作的实现及其区别

使用 SAP ABAP SEGW 事物码实现 OData 服务的修改操作时,对于消费端通过 PATCH/MERGE 和 PUT 这三种不同类型的 HTTP 请求触发的场景,我们应该在 UPDATE_ENTITY 方法里用 IF 分支分别进行处理,原因就在于 GET_ENTITY 方法是否在修改处理逻辑的过程中被触发。......

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2462
上一篇: Win32的菜单编程
下一篇: php5和mysql5的安装配置
MikeFeng
博客等级 码龄23年 27粉丝 29原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值