Use win32 http-server-api to implement http server under vs, and implement get and post requests

Foreword:

     Under Windows VS, use C++ to implement the http server. As far as I know, you can use win32 http-server-api or libevent to implement it. The following example is an http server implemented with win32 http-server-api. It supports get and post requests. This article provides the demo project download of the server. The demo is under vs2008, and the project can be modified to support other vs versions.

    Win32 http-server-api official document access path:
        https://learn.microsoft.com/zh-cn/windows/win32/http/http-api-start-page

1: Basic API introduction

1.HttpInitialize initializes the WinHTTP function library;
2.HttpCreateHttpHandle creates an HTTP queue handle to receive HTTP requests;
3.HttpAddUrl binds the URL to be monitored, and writes it as http:// :80/ to indicate HTTP requests on port 80 of all network cards
4. Create a thread to process the HTTP request queue; 5. HttpReceiveHttpRequest
Call this function in the thread to receive HTTP requests. 6.
HttpReceiveRequestEntityBody This function is used to receive the BODY part of the HTTP request, if the data is very long, it needs to be called multiple times;

Two: demo core code

httpserver.h

/* 
 * Filename:      	 httpserver.h
 * Author:		     ybLin
 * Description:  	 httpserver
 * *******************************************************/
#pragma once
#include "stdafx.h"
#include <http.h>

class CHttpServer;

int myprint(const char* msg, ...);
int myprint(const wchar_t *msg, ...);

typedef enum REQUEST_TYPE_E
{
    REQUEST_TYPE_GET = 0,
    REQUEST_TYPE_POST
};

class IHttpServerListener
{
public:
    virtual BOOL OnRecvRequest(CHttpServer *inst, PHTTP_REQUEST request, enum REQUEST_TYPE_E nRequestType)=0;
};

class CHttpServer
{
public:
    CHttpServer();
    BOOL Init(int port, IHttpServerListener *pListener);
    BOOL DeInit();

    //服务器发送响应
    DWORD SendHttpGetResponse(PHTTP_REQUEST pRequest,USHORT StatusCode,PSTR pReason,PSTR pEntityString);
    DWORD SendHttpPostResponse(PHTTP_REQUEST pRequest);

    //处理接收请求
    static UINT AFX_CDECL RecvRequestThread(LPVOID param);

private:
    BOOL DoReceiveRequests();
    void InitUri(INT nPort);


private:
    wchar_t* m_wUrI[32];
    int     m_nUriCnt;
    LPBYTE m_req_buffer;
    HANDLE m_req_queue;   
    UINT   m_req_buffer_size;
    CWinThread *m_thread;
    IHttpServerListener *m_listener;
};

httpserver.cpp

#include "StdAfx.h"
#include "httpserver.h"
#include <iphlpapi.h>
#include <string>
#pragma comment(lib, "httpapi.lib")
#pragma comment(lib,"Iphlpapi.lib") 

#define RECV_BUF_SIZE 4096
#define MAX_ULONG_STR ((ULONG) sizeof("4294967295"))
#define INITIALIZE_HTTP_RESPONSE( resp, status, reason )    \
    do                                                      \
    {                                                       \
        RtlZeroMemory( (resp), sizeof(*(resp)) );           \
        (resp)->StatusCode = (status);                      \
        (resp)->pReason = (reason);                         \
        (resp)->ReasonLength = (USHORT) strlen(reason);     \
    } while (FALSE)
#define ADD_KNOWN_HEADER(Response, HeaderId, RawValue)               \
    do                                                               \
    {                                                                \
        (Response).Headers.KnownHeaders[(HeaderId)].pRawValue =      \
                                                          (RawValue);\
        (Response).Headers.KnownHeaders[(HeaderId)].RawValueLength = \
            (USHORT) strlen(RawValue);                               \
    } while(FALSE)
#define ALLOC_MEM(cb) HeapAlloc(GetProcessHeap(), 0, (cb))
#define FREE_MEM(ptr) HeapFree(GetProcessHeap(), 0, (ptr))

// 打印函数
int myprint(const char* msg, ...)        					
{
	char buf[1024] = {0};
	char test[1024] = {0};
	va_list  va;
	time_t now = time(NULL);
	char szTime[32] = {0};
	struct tm t;
	localtime_s(&t, &now);
	_snprintf_s(szTime, sizeof(szTime), sizeof(szTime)-1, "%4d-%02d-%02d %02d:%02d:%02d",
        t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
	va_start (va, msg);
	_vsnprintf_s(buf, sizeof(buf) - 1, (char*)msg, va);
	va_end(va);

	_snprintf_s(test, sizeof(test), sizeof(test) - 1, "[Time:%s]===%s===\n", szTime, buf);
	OutputDebugStringA(test);
	return 0;
}

int myprint(const wchar_t *msg, ...)
{
    va_list vlArgs = NULL;
	va_start(vlArgs, msg);
	size_t nLen = _vscwprintf(msg, vlArgs) + 1;
	wchar_t *strBuffer = new wchar_t[nLen];
	_vsnwprintf_s(strBuffer, nLen, nLen, msg, vlArgs);
	va_end(vlArgs);
	OutputDebugStringW(strBuffer);
	delete [] strBuffer;

    return 0;
}

//多网卡获取PCI网卡的IP
void getAdapterInfoWithWindows(std::string& LoacalIp)
{
    //PIP_ADAPTER_INFO结构体存储本机网卡信息,包括本地网卡、无线网卡和虚拟网卡
    PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
    ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
    //调用GetAdaptersInfo函数,填充pAdapterInfo指针变量,其中ulOutBufLen参数既是输入也是输出
    if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS)
    {
        //如果分配失败,释放后重新分配
        delete pAdapterInfo;
        //pAdapterInfo = NULL;
        pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
    }
    if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR)
    {
        while (pAdapterInfo)
        {
            myprint("Adapter Name:%s", pAdapterInfo->AdapterName);
            myprint("Adapter IP Address:%s", pAdapterInfo->IpAddressList.IpAddress.String); 

            //pAdapter->Description中包含"PCI"为本地网卡,pAdapter->Type是71为无线网卡
            if((strstr(pAdapterInfo->Description,"PCI") > 0 || strstr(pAdapterInfo->Description,"Intel") > 0) 
                && (pAdapterInfo->Type != 71))
            {
                //这里假设每个网卡只有一个IP
                char * ipAddress = pAdapterInfo->IpAddressList.IpAddress.String;
                char tempIpAddress[3]={'\0'};
                memcpy(tempIpAddress,ipAddress,3);

                myprint("Adapter Name:%s", pAdapterInfo->AdapterName);
                myprint("Adapter IP Address:%s", pAdapterInfo->IpAddressList.IpAddress.String); 
                myprint("Adapter IP Address:%s", ipAddress); 
                LoacalIp = pAdapterInfo->IpAddressList.IpAddress.String;
            }
            pAdapterInfo = pAdapterInfo->Next;
        }
    }
    else
    {
        myprint("Call to GetAdaptersInfo failed.\n");
    }
    if(pAdapterInfo)
    {
        GlobalFree(pAdapterInfo);
    }
}

wchar_t * char2wchar(const char* cchar) 
{     
    wchar_t *m_wchar;    
    int len = MultiByteToWideChar(CP_ACP ,0,cchar ,strlen( cchar), NULL,0);     
    m_wchar= new wchar_t[len+1];     
    MultiByteToWideChar(CP_ACP ,0,cchar,strlen( cchar),m_wchar,len);     
    m_wchar[len]= '\0' ;    
    return m_wchar; 
} 
/
CHttpServer::CHttpServer()
{
    m_thread = NULL;
    m_req_queue  = NULL;
    m_req_buffer = NULL;
    m_req_buffer_size = RECV_BUF_SIZE;
}

void CHttpServer::InitUri(INT nPort)
{
    char sUrl[256] = {0};
    std::string sLocalIP;
    getAdapterInfoWithWindows(sLocalIP);
    const char* pIP = sLocalIP.data();
    
    _snprintf(sUrl, sizeof(sUrl)-1, "http://%s:%d/config", pIP, nPort);
    m_wUrI[0] = char2wchar(sUrl);

    _snprintf(sUrl, sizeof(sUrl)-1, "http://%s:%d/network", pIP, nPort);
    m_wUrI[1] = char2wchar(sUrl);
    
    m_nUriCnt = 2;
}

BOOL CHttpServer::Init(INT nPort, IHttpServerListener *pListener)
{
    ULONG retCode;    
    HTTPAPI_VERSION version = HTTP_VERSION_1_0;

    retCode = HttpInitialize(version,HTTP_INITIALIZE_SERVER,NULL);
    if(retCode != NO_ERROR)
    {
        myprint("HttpInitialize error(%u)!\r\n", retCode);
        goto Fail;
    }

    retCode = HttpCreateHttpHandle(&m_req_queue, 0);
    if(retCode != NO_ERROR)
    {
        myprint("HttpCreateHttpHandle error(%u)!\n", retCode);
        HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
        return FALSE;
    }

    InitUri(nPort);

    for(int i = 0; i < m_nUriCnt; i++)
    {
        retCode = HttpAddUrl(m_req_queue, m_wUrI[i], NULL);
        if(retCode != NO_ERROR)
        {
            myprint("HttpAddUrl error(%u)!\n", retCode);
            goto Fail;
        }
    }
   
    m_req_buffer = (LPBYTE)malloc(m_req_buffer_size); //缓冲区大小
    if(NULL == m_req_buffer)
    {
        goto Fail;
    }
    
    m_listener = pListener;
    m_thread = AfxBeginThread(RecvRequestThread, this);

    myprint("Http Server Create success");
    return TRUE;

Fail:
    for(int i = 0; i < m_nUriCnt; i++)
    {
        HttpRemoveUrl(m_req_queue, m_wUrI[i]);
    }
    m_nUriCnt = 0;

    if(m_req_queue)
    {
        CloseHandle(m_req_queue);
    }

    HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
    
    return FALSE;
}

BOOL CHttpServer::DeInit()
{
    for(int i = 0; i < m_nUriCnt; i++)
    {
        HttpRemoveUrl(m_req_queue, m_wUrI[i]);
    }
    m_nUriCnt = 0;

    if(m_req_queue)
    {
        CloseHandle(m_req_queue);
        HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
        m_req_queue = NULL;
    }
    if(m_req_buffer)
    {
        free(m_req_buffer);
        m_req_buffer = NULL;
    }
    if(m_thread)
    {
        m_thread->Delete();
        m_thread = NULL;
    }
    return TRUE;
}

DWORD CHttpServer::SendHttpGetResponse(PHTTP_REQUEST pRequest,USHORT StatusCode,
    PSTR pReason,PSTR pEntityString)
{
    HTTP_RESPONSE   response;    
    HTTP_DATA_CHUNK dataChunk;    
    DWORD           result;    
    DWORD           bytesSent;
    
    // Initialize the HTTP response structure.
    do                                                          
    {                                                               
    	RtlZeroMemory(&response, sizeof(response));                   
    	(response).StatusCode = (StatusCode);                              
    	(response).pReason = (pReason);                                 
    	(response).ReasonLength = (USHORT) strlen(pReason);         
    } while (FALSE);
    
    // Add a known header.
    LPCSTR type = "text/html";
    do                                                                 
    {                                                                       
    	response.Headers.KnownHeaders[HttpHeaderContentType].pRawValue =  type;        
    	response.Headers.KnownHeaders[HttpHeaderContentType].RawValueLength = (USHORT) strlen(type);  
    } while(FALSE);

    if(pEntityString)    
    {
        // Add an entity chunk.       
        dataChunk.DataChunkType = HttpDataChunkFromMemory;        
        dataChunk.FromMemory.pBuffer = pEntityString;        
        dataChunk.FromMemory.BufferLength =  (ULONG) strlen(pEntityString);        
        response.EntityChunkCount = 1;        
        response.pEntityChunks = &dataChunk;    
    }
    
    // Because the entity body is sent in one call, it is not
    // required to specify the Content-Length.    
    result = HttpSendHttpResponse(m_req_queue,         // ReqQueueHandle                    
                                  pRequest->RequestId, // Request ID
                                  0,                   // Flags                    
                                  &response,           // HTTP response
                                  NULL,                // pReserved1                    
                                  &bytesSent,          // bytes sent  (OPTIONAL)
                                  NULL,                // pReserved2  (must be NULL)
                                  0,                   // Reserved3   (must be 0)
                                  NULL,                // LPOVERLAPPED(OPTIONAL)
                                  NULL                 // pReserved4  (must be NULL)                    
                                  ); 
    if(result != NO_ERROR)    
    {
        myprint("HttpSendHttpResponse failed with %lu \n", result);    
    }
    return result;
}

DWORD CHttpServer::SendHttpPostResponse(PHTTP_REQUEST pRequest)
{
    HTTP_RESPONSE   response;
    DWORD           result;
    DWORD           bytesSent;
    PUCHAR          pEntityBuffer;
    ULONG           EntityBufferLength;
    ULONG           BytesRead;
    ULONG           TempFileBytesWritten;
    HANDLE          hTempFile;
    TCHAR           szTempName[MAX_PATH + 1];
    CHAR            szContentLength[MAX_ULONG_STR];
    HTTP_DATA_CHUNK dataChunk;
    ULONG           TotalBytesRead = 0;
    BytesRead  = 0;
    hTempFile  = INVALID_HANDLE_VALUE;

    // 为实体缓冲区分配空间。 缓冲区可按需增加。
    EntityBufferLength = 2048;
    pEntityBuffer      = (PUCHAR) ALLOC_MEM( EntityBufferLength );
    if (pEntityBuffer == NULL)
    {
        result = ERROR_NOT_ENOUGH_MEMORY;
        wprintf(L"Insufficient resources \n");
        goto Done;
    }
    // 初始化HTTP response结构体.
    INITIALIZE_HTTP_RESPONSE(&response, 200, "OK");
    // 对于POST,从客户端回显实体
    // 注意: 如果HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY标识通过HttpReceiveHttpRequest()
	//       传递,则entity将是HTTP_REQUEST的一部分(使用pEntityChunks字段).因为此标识
	//       未被传递,则entity不在HTTP_REQUEST中.
    if(pRequest->Flags & HTTP_REQUEST_FLAG_MORE_ENTITY_BODY_EXISTS)
    {
        myprint("post response 111");
        // 实体主体通过多个调用发送. 收集这些在一个文件并回发.创建一个临时文件
        if(GetTempFileName(
                ".",
                "New",
                0,
                szTempName
                ) == 0)
        {
            result = GetLastError();
            myprint("GetTempFileName failed with %lu \n", result);
            goto Done;
        }
        hTempFile = CreateFile(
                        szTempName,
                        GENERIC_READ | GENERIC_WRITE,
                        0,                  // Do not share.
                        NULL,               // No security descriptor.
                        CREATE_ALWAYS,      // Overrwrite existing.
                        FILE_ATTRIBUTE_NORMAL,    // Normal file.
                        NULL
                        );
        if(hTempFile == INVALID_HANDLE_VALUE)
        {
            result = GetLastError();
            myprint("Cannot create temporary file. Error %lu \n",
                     result);
            goto Done;
        }
        do
        {
            // 从请求中读取entity chunk.
            BytesRead = 0;
            result = HttpReceiveRequestEntityBody(
                        m_req_queue,
                        pRequest->RequestId,
                        0,
                        pEntityBuffer,
                        EntityBufferLength,
                        &BytesRead,
                        NULL
                        );
            switch(result)
            {
                case NO_ERROR:
                    if(BytesRead != 0)
                    {
                        TotalBytesRead += BytesRead;
                        WriteFile(
                                hTempFile,
                                pEntityBuffer,
                                BytesRead,
                                &TempFileBytesWritten,
                                NULL
                                );
                    }
                    break;
                case ERROR_HANDLE_EOF:
                    // The last request entity body has been read.
                    // Send back a response.
                    //
                    // To illustrate entity sends via
                    // HttpSendResponseEntityBody, the response will
                    // be sent over multiple calls. To do this,
                    // pass the HTTP_SEND_RESPONSE_FLAG_MORE_DATA
                    // flag.
                    if(BytesRead != 0)
                    {
                        TotalBytesRead += BytesRead;
                        WriteFile(
                                hTempFile,
                                pEntityBuffer,
                                BytesRead,
                                &TempFileBytesWritten,
                                NULL
                                );
                    }
                    // Because the response is sent over multiple
                    // API calls, add a content-length.
                    //
                    // Alternatively, the response could have been
                    // sent using chunked transfer encoding, by
                    // passimg "Transfer-Encoding: Chunked".
                    //
                    // NOTE: Because the TotalBytesread in a ULONG
                    //       are accumulated, this will not work
                    //       for entity bodies larger than 4 GB.
                    //       For support of large entity bodies,
                    //       use a ULONGLONG.
                    sprintf_s(szContentLength, MAX_ULONG_STR, "%lu", TotalBytesRead);
                    ADD_KNOWN_HEADER(
                            response,
                            HttpHeaderContentLength,
                            szContentLength
                            );
                    result =
                        HttpSendHttpResponse(
                               m_req_queue,           // ReqQueueHandle
                               pRequest->RequestId, // Request ID
                               HTTP_SEND_RESPONSE_FLAG_MORE_DATA,
                               &response,       // HTTP response
                               NULL,            // pReserved1
                               &bytesSent,      // bytes sent-optional
                               NULL,            // pReserved2
                               0,               // Reserved3
                               NULL,            // LPOVERLAPPED
                               NULL             // pReserved4
                               );
                    if(result != NO_ERROR)
                    {
                        myprint(
                           "HttpSendHttpResponse failed with %lu \n",
                           result
                           );
                        goto Done;
                    }
                    // Send entity body from a file handle.
                    dataChunk.DataChunkType =
                        HttpDataChunkFromFileHandle;
                    dataChunk.FromFileHandle.
                        ByteRange.StartingOffset.QuadPart = 0;
                    dataChunk.FromFileHandle.
                        ByteRange.Length.QuadPart =
                                          HTTP_BYTE_RANGE_TO_EOF;
                    dataChunk.FromFileHandle.FileHandle = hTempFile;
                    result = HttpSendResponseEntityBody(
                                m_req_queue,
                                pRequest->RequestId,
                                0,           // This is the last send.
                                1,           // Entity Chunk Count.
                                &dataChunk,
                                NULL,
                                NULL,
                                0,
                                NULL,
                                NULL
                                );
                    if(result != NO_ERROR)
                    {
                       myprint(
                          "HttpSendResponseEntityBody failed %lu\n",
                          result
                          );
                    }
                    myprint("post response success.");
                    goto Done;
                    break;
                default:
                  myprint(
                   "HttpReceiveRequestEntityBody failed with %lu \n",
                   result);
                  goto Done;
            }
        } while(TRUE);
    }
    else
    {
        myprint("post response 222");
        // 此请求没有实体主体。
        result = HttpSendHttpResponse(
                   m_req_queue,           // ReqQueueHandle
                   pRequest->RequestId, // Request ID
                   0,
                   &response,           // HTTP response
                   NULL,                // pReserved1
                   &bytesSent,          // bytes sent (optional)
                   NULL,                // pReserved2
                   0,                   // Reserved3
                   NULL,                // LPOVERLAPPED
                   NULL                 // pReserved4
                   );
        if(result != NO_ERROR)
        {
            myprint("HttpSendHttpResponse failed with %lu \n",
                    result);
        }
    }
    
Done:
    if(pEntityBuffer)
    {
        FREE_MEM(pEntityBuffer);
    }
    if(INVALID_HANDLE_VALUE != hTempFile)
    {
        CloseHandle(hTempFile);
        DeleteFile(szTempName);
    }
    return result;
}

UINT CHttpServer::RecvRequestThread(LPVOID param)
{
    CHttpServer *self;
    self = (CHttpServer *)param;
    self->DoReceiveRequests();
    Sleep(INFINITE);
    return 0;
}

BOOL CHttpServer::DoReceiveRequests(void)
{
    ULONG         ret;
    DWORD         bytes_read;
    PHTTP_REQUEST request;
    request = (PHTTP_REQUEST)m_req_buffer;
    while(1)
    {
        RtlZeroMemory(request, m_req_buffer_size);
        ret = HttpReceiveHttpRequest(m_req_queue, HTTP_NULL_ID, 0, request,
                m_req_buffer_size, &bytes_read, NULL);
        if(NO_ERROR == ret)
        {
            switch(request->Verb)
            {  
                case HttpVerbGET:
                    m_listener->OnRecvRequest(this, request, REQUEST_TYPE_GET);
                break;
                case HttpVerbPOST:
                    m_listener->OnRecvRequest(this, request, REQUEST_TYPE_POST);
                break;
                default:
                    myprint("unknown request %ws \n", request->CookedUrl.pFullUrl);
                    SendHttpGetResponse(request, 503, "Not Implemented", "Not Implemented \r\n");
                break;
            }            
            continue;
        }

        if(ret == ERROR_OPERATION_ABORTED)
        {
            return FALSE;
        }
        if(ret == ERROR_INVALID_HANDLE)
        {
            return FALSE;
        }
    }
    return TRUE;
}

Use:
demoDlg.h


// demoDlg.h : 头文件
//
#pragma once
#include "httpserver.h"

// CdemoDlg 对话框
class CdemoDlg : public CDialog, public IHttpServerListener
{
// 构造
public:
	CdemoDlg(CWnd* pParent = NULL);	// 标准构造函数
	~CdemoDlg();
// 对话框数据
	enum { IDD = IDD_DEMO_DIALOG };
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
    BOOL OnRecvRequest(CHttpServer *inst, PHTTP_REQUEST request, enum REQUEST_TYPE_E nRequestType);
    CHttpServer m_server;
    bool m_bWait;

// 实现
protected:
	HICON m_hIcon;
	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
};

demoDlg.cpp


// demoDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "demo.h"
#include "demoDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CdemoDlg 对话框


CdemoDlg::CdemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CdemoDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_server.Init(54321, this);
    
}

CdemoDlg::~CdemoDlg()
{
    m_server.DeInit();
}

void CdemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BOOL CdemoDlg::OnRecvRequest(CHttpServer *inst, PHTTP_REQUEST request, enum REQUEST_TYPE_E nRequestType)
{
    //此处做接口处理
    if(inst && request)
    {
        myprint(L"recv:%ws", request->CookedUrl.pFullUrl);
        myprint(L"recv:%ws", request->CookedUrl.pAbsPath);
        myprint(L"recv:%ws", request->CookedUrl.pQueryString);
        
        if(nRequestType == REQUEST_TYPE_POST)
        {
            inst->SendHttpPostResponse(request);
        }
        else
        {
            char paramBuf[512] = {0};
            char sTemp[512] = {0};
            std::string sId;
            int nParam = 0;
            bool bCtlOk = false;
            sprintf(paramBuf,"%S",request->CookedUrl.pQueryString+1);

            vector<char*> res_split;
            const char split[] = "&";
            char* res = strtok(paramBuf, split);
            while (res != NULL)
            {
                res_split.push_back(res);
                res = strtok(NULL, split);
            }

            for(int i = 0; i < res_split.size(); i++)
            {
                char* pos;
                if(pos = strstr(res_split[i], "setId="))
                {
                    sscanf(pos, "%*[^=]=%[^\n] ", sTemp);
                    sId = sTemp;
                    myprint("sId:%s", sTemp);
                    bCtlOk = true;
                }

                if(pos = strstr(res_split[i], "setParam="))
                {
                    sscanf(pos, "%*[^=]=%[^\n] ", sTemp);
                    nParam = atoi(sTemp); 
                    myprint("nParam:%s", sTemp);
                    bCtlOk = true;
                }
            }
            if(bCtlOk)
            {
                //可以开启超时等待响应
                /*
                m_bWait = true; //等待
                int nWaitTime = 50;//超时5s
                while(m_bWait && nWaitTime--)
                {
                    Sleep(100);
                }*/

                inst->SendHttpGetResponse(request, 200, "OK", 
                                    "OK Set Success. \r\n");
            }   
        }      

    }
        
    return true;
}

BEGIN_MESSAGE_MAP(CdemoDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// CdemoDlg 消息处理程序

BOOL CdemoDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。
void CdemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文
		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CdemoDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

Three: Project download

https://download.csdn.net/download/linyibin_123/87580091

Four: Test results

insert image description here

Guess you like

Origin blog.csdn.net/linyibin_123/article/details/129562224