vs下使用win32 http-server-api实现http服务器,实现get和post请求

前言:

     在windows VS下,用C++实现http服务器,目前据我所知,可以使用win32 http-server-api进行实现,也可以使用libevent进行实现,以下例子是用win32 http-server-api实现的http服务器,支持get和post请求,本文提供服务器的demo工程下载,该demo是在vs2008下,可以修改工程支持其他vs版本。

    win32 http-server-api官方文档访问路径:
        https://learn.microsoft.com/zh-cn/windows/win32/http/http-api-start-page

一:基本API介绍

1.HttpInitialize 初始化WinHTTP函数库;
2.HttpCreateHttpHandle 创建一个HTTP队列句柄,用来接收HTTP请求;
3.HttpAddUrl 绑定要监听的URL,写为http://:80/表示所有网卡80端口的HTTP请求都处理,其中的号可以改为IP地址;
4.创建一个线程用来处理HTTP请求队列;
5.HttpReceiveHttpRequest 在线程中调用此函数,接收HTTP请求,在返回的PHTTP_REQUEST结构中有我们想要的各种数据;
6.HttpReceiveRequestEntityBody 这个函数用来接收HTTP请求的BODY部分,如果数据很长需要多次调用;

二:demo核心代码

httpserver.h

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

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 
#include 
#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;
}

使用:
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 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(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(m_hIcon);
}

三:工程下载

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

四:测试结果

vs下使用win32 http-server-api实现http服务器,实现get和post请求_第1张图片

你可能感兴趣的:(MFC,服务器,http,windows)