Share via

Question about httpPlatformHandler

Roland Smith 1 Reputation point
2022-06-11T16:51:45.693+00:00

I am trying to write a server app in C++ using Winsock and httpPlatformHandler. When searching the web there are tons of pages about configuring but coding for it is pretty much nothing.

Question 1: How do I code it for clean shutdown? If I need to recompile, right now I have to run Task Manager and kill the w3wp.exe task. A restart in IIS Manager just hangs.

Question 2: It works fine from a browser. If I call the URL from another app using the GET method and some data, where does the data come in? The server app recv function isn't getting it, it only gets the headers. If the other app uses the POST method, the server app doesn't get anything from the recv.

Windows development | Internet Information Services
Developer technologies | C++
Developer technologies | C++

A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.

0 comments No comments

2 answers

Sort by: Most helpful
  1. Roland Smith 1 Reputation point
    2022-06-13T16:15:52.207+00:00

    Question 1: I am testing it using a browser so VS doesn't kill the exe while compiling.
    Question 2: I wrote a test app that uses HttpClient. When I send data along with a GET, I see a Content-Length header in the headers returned by recv but not the data. If I send data with a POST, the recv returns nothing. I need to know how httpPlatformHandler transfers posted data to the executable.

    Here is the app. It is compiled using Unicode because the real processing I haven't added yet requires it. For now it returns the current datetime and the data from the recv.

       #include <winsock2.h>  
       #include <ws2tcpip.h>  
       #include <tchar.h>  
       #include <stdio.h>  
       #include <string>  
       using std::string;  
         
       #pragma comment (lib, "Ws2_32.lib")  
         
       #pragma warning (disable: 6387)  
         
       void GetLastError(int iErrorNum);  
       void SendResponse(SOCKET client, LPCSTR lpstrResponse);  
       void SetBlockingMode(SOCKET sock, BOOL blocking);  
       void WriteToLogFile(LPCSTR lpstrMessage);  
       int WebServer(LPTSTR lpstrServiceName);  
         
       int _tmain(int argc, TCHAR* argv[])  
       {  
          TCHAR szServiceName[MAX_PATH];  
         
          wmemset(szServiceName, 0x00, _countof(szServiceName));  
         
          // Get ServiceName (port)  
          if (argc == 1) {  
             _tcscpy_s(szServiceName, _countof(szServiceName), L"9000");  
          }  
          else {  
             _tcscpy_s(szServiceName, _countof(szServiceName), argv[1]);  
          }  
         
          // Start web server  
          return WebServer(szServiceName);  
       }  
         
       void GetLastError(int iErrorNum)  
       {  
          CHAR szBuffer[MAX_PATH];  
         
          memset(szBuffer, 0x00, sizeof(szBuffer));  
         
          sprintf_s(szBuffer, sizeof(szBuffer), "ErrorNum: %d", iErrorNum);  
          WriteToLogFile(szBuffer);  
         
          FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL,  
             iErrorNum, LANG_NEUTRAL, szBuffer, MAX_PATH, 0);  
         
          WriteToLogFile(szBuffer);  
         
          WSASetLastError(0);  
       }  
         
       void SendResponse(SOCKET client, LPCSTR lpstrResponse)  
       {  
          int length = 0;  
         
          length = strlen(lpstrResponse);  
         
          send(client, lpstrResponse, length, 0);  
       }  
         
       void SetBlockingMode(SOCKET sock, BOOL blocking)  
       {  
          u_long argp;  
         
          if (blocking) {  
             argp = 0;  
          }  
          else {  
             argp = 1;  
          }  
         
          ioctlsocket(sock, FIONBIO, &argp);  
       }  
         
       void WriteToLogFile(LPCSTR lpstrMessage)  
       {  
          HANDLE hFile;  
          DWORD dwWritten = 0;  
         
          hFile = CreateFileA("C:\\Temp\\LogFile.txt",  
             FILE_APPEND_DATA, FILE_SHARE_WRITE, NULL,  
             OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);  
          if (hFile != INVALID_HANDLE_VALUE) {  
             WriteFile(hFile, lpstrMessage, (DWORD)strlen(lpstrMessage), &dwWritten, 0);  
             WriteFile(hFile, "\r\n", 2, &dwWritten, 0);  
             CloseHandle(hFile);  
          }  
       }  
         
       int WebServer(LPTSTR lpstrServiceName)  
       {  
          WSADATA wsaData;  
          int iResult = 0;  
          CHAR szRecvBuffer[1024];  
          string ReceivedData;  
         
          SYSTEMTIME lt;  
          char szMsgText[MAX_PATH];  
          char szTemp[34];  
         
          SOCKET ListenSocket = INVALID_SOCKET;  
          SOCKET ClientSocket = INVALID_SOCKET;  
         
          struct addrinfoW* result = NULL;  
          struct addrinfoW hints;  
         
          memset(szMsgText, 0x00, sizeof(szMsgText));  
          memset(szTemp, 0x00, sizeof(szTemp));  
         
          // Start Winsock  
          iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);  
          if (iResult != 0) {  
             WriteToLogFile("WSAStartup error: ");  
             GetLastError(iResult);  
             return 1;  
          }  
         
          // Initialze the structure  
          ZeroMemory(&hints, sizeof(hints));  
          hints.ai_family = AF_INET;  
          hints.ai_socktype = SOCK_STREAM;  
          hints.ai_protocol = IPPROTO_TCP;  
          hints.ai_flags = AI_PASSIVE;  
         
          // Resolve the server address and port  
          iResult = GetAddrInfoW(NULL, lpstrServiceName, &hints, &result);  
          if (iResult != 0) {  
             WriteToLogFile("GetAddrInfoW error: ");  
             GetLastError(iResult);  
             WSACleanup();  
             return 1;  
          }  
         
          // Create a SOCKET for connecting to server  
          ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);  
          if (ListenSocket == INVALID_SOCKET) {  
             WriteToLogFile("Socket error: ");  
             GetLastError(WSAGetLastError());  
             FreeAddrInfoW(result);  
             WSACleanup();  
             return 1;  
          }  
         
          // Setup the TCP listening socket  
          iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);  
          if (iResult == SOCKET_ERROR) {  
             WriteToLogFile("Bind error: ");  
             GetLastError(WSAGetLastError());  
             FreeAddrInfoW(result);  
             WSACleanup();  
             return 1;  
          }  
         
          // Cleanup  
          FreeAddrInfoW(result);  
         
          // Listen for connections  
          iResult = listen(ListenSocket, SOMAXCONN);  
          if (iResult == SOCKET_ERROR) {  
             WriteToLogFile("Listen error: ");  
             GetLastError(WSAGetLastError());  
             closesocket(ListenSocket);  
             WSACleanup();  
             return 1;  
          }  
         
          // Make the socket blocking  
          SetBlockingMode(ListenSocket, TRUE);  
         
          while (0 == 0)  
          {  
             // Accept incoming connection  
             ClientSocket = accept(ListenSocket, NULL, NULL);  
             if (ClientSocket == INVALID_SOCKET) {  
                WriteToLogFile("Accept error: ");  
                GetLastError(WSAGetLastError());  
                closesocket(ListenSocket);  
                WSACleanup();  
                return 1;  
             }  
         
             // Make the socket non-blocking  
             SetBlockingMode(ClientSocket, FALSE);  
         
             // Receive the data  
             ReceivedData.clear();  
             do {  
                memset(szRecvBuffer, 0x00, sizeof(szRecvBuffer));  
         
                iResult = recv(ClientSocket, szRecvBuffer, sizeof(szRecvBuffer) - 1, 0);  
         
                switch (iResult) {  
                case SOCKET_ERROR:  
                   break;  
                case 0:  
                   break;  
                default:  
                   ReceivedData.append(szRecvBuffer);  
                   break;  
                }  
             } while (iResult > 0);  
         
             // determine the current time  
             GetLocalTime(&lt);  
         
             // format the time into a localized string  
             strcpy_s(szMsgText, sizeof(szMsgText), "Current Timestamp: ");  
             GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &lt, NULL, szTemp, sizeof(szTemp));  
             strcat_s(szMsgText, sizeof(szMsgText), szTemp);  
             strcat_s(szMsgText, sizeof(szMsgText), " ");  
             GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER + TIME_FORCE24HOURFORMAT, &lt, NULL, szTemp, sizeof(szTemp));  
             strcat_s(szMsgText, sizeof(szMsgText), szTemp);  
             sprintf_s(szTemp, sizeof(szTemp), ".%03d", lt.wMilliseconds);  
             strcat_s(szMsgText, sizeof(szMsgText), szTemp);  
             strcat_s(szMsgText, sizeof(szMsgText), "\r\n");  
         
             // Send reply  
             SendResponse(ClientSocket, "HTTP/1.1 200 OK\r\n");  
             SendResponse(ClientSocket, "Content-Type: text/plain; charset=UTF-8\r\n");  
             SendResponse(ClientSocket, "\r\n");  
             SendResponse(ClientSocket, szMsgText);  
             SendResponse(ClientSocket, "\r\n");  
             if (ReceivedData.length() > 0) {  
                SendResponse(ClientSocket, "ReceivedData:\r\n");  
                SendResponse(ClientSocket, "\r\n");  
                SendResponse(ClientSocket, ReceivedData.c_str());  
             }  
         
             // Shutdown client socket  
             iResult = shutdown(ClientSocket, SD_SEND);  
         
             // Close client socket  
             closesocket(ClientSocket);  
          }  
         
          // Close listen socket  
          closesocket(ListenSocket);  
         
          // Cleanly shut down Winsock  
          WSACleanup();  
         
          return 0;  
       }  
    

  2. Bruce Zhang-MSFT 3,776 Reputation points
    2022-06-13T02:50:35.477+00:00

    Hi @Roland Smith ,

    Question 1: How do I code it for clean shutdown? If I need to recompile, right now I have to run Task Manager and kill the w3wp.exe task. A restart in IIS Manager just hangs.

    Why you need to shut down process manually? If you recompile, application pool will auto recycle process of application. Create a new w3wp.exe process and delete old one.

    Question 2: It works fine from a browser. If I call the URL from another app using the GET method and some data, where does the data come in?

    It seems like a winsock and C++ issue. How your function call the url to get data and how the url response data? In JSON or any other data type? If it is a http response and request, you'd better use Fiddler or Postman to check response and request body.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Bruce Zhang

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.