【问题标题】:POST form data using WinInet c++使用 WinInet C++ POST 表单数据
【发布时间】:2011-07-30 06:05:19
【问题描述】:

我试图让这个程序连接到一个网站并提交表单数据以便登录,但我不知道我做错了什么。我听说过 curl 和 Winsock 之类的其他工具,但我选择了 WinINet 库。所以只是为了测试这个程序,我一直在使用网站 Pastebin 来发布。到目前为止,我还没有看到任何结果。如果这个程序成功地发布了表单数据,它将给我他们网站上帖子位置的标题。

我是否正确地编写了表单数据 char*?我在其他 stackoverflow 帖子中看到,他们在某个数字之前有大量破折号,然后放入表单数据。

我需要添加一些东西让它模拟点击提交按钮吗?
我需要为表单上的每个元素写出值吗?

我已经尝试过 HttpAddRequestHeaders,但对我没有帮助。

此外,我在 HttpOpenRequest 上收到 ERROR_INSUFFICIENT_BUFFER 错误,但它仍然返回有效的 HINTERNET。

#include <Windows.h>
#include <WinInet.h>
#include <iostream>

#pragma comment( lib,"Wininet.lib")
using namespace std;

char* getheaders(HINTERNET hRequest){
    DWORD dwInfoLevel=HTTP_QUERY_RAW_HEADERS_CRLF;
    DWORD dwInfoBufferLength=10;
    char* pInfoBuffer=(char*)malloc(dwInfoBufferLength+1);
    while(!HttpQueryInfo(hRequest,dwInfoLevel,pInfoBuffer,&dwInfoBufferLength,NULL)){
        if (GetLastError()==ERROR_INSUFFICIENT_BUFFER){
            free(pInfoBuffer);
            pInfoBuffer=(char*)malloc(dwInfoBufferLength+1);
        }else{
            fprintf(stderr,"HttpQueryInfo failed, error = %d (0x%x)\n",GetLastError(),GetLastError());
            break;
        }
    }
    pInfoBuffer[dwInfoBufferLength] = '\0';
    return pInfoBuffer;
}

void readfile(HINTERNET hRequest,char** buffs,int size){
    DWORD dwBytesAvailable;
    DWORD dwBytesRead;
    for(int i=0;i<size;i++){
        if(!InternetQueryDataAvailable(hRequest,&dwBytesAvailable,0,0)) break;
        buffs[i]=(char*)malloc(dwBytesAvailable+1);
        bool bResult=InternetReadFile(hRequest,buffs[i],dwBytesAvailable,&dwBytesRead);
        if(!bResult | dwBytesRead==0) break;
    }
}


int main(int argc,char** argv){
    char* hdrs="Content-Type: application/x-www-form-urlencoded";
    char* frmdata="paste_code=test";
    LPCSTR accept[2]={"*/*", NULL};

    HINTERNET hSession = InternetOpen("http generic",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    HINTERNET hConnect = InternetConnect(hSession, "www.pastebin.com",INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
    HINTERNET hRequest = HttpOpenRequest(hConnect, "GET","/", NULL, NULL, accept, 0, 0);
    //ERROR_INSUFFICIENT_BUFFER (122) with "accept".

    bool send=HttpSendRequest(hRequest, hdrs, strlen(hdrs), NULL,NULL);
    if(!send){
        printf("HttpSendRequest failed, code=%d",GetLastError());
        system("pause>nul");
        return 0;
    }

    char* heads=getheaders(hRequest);
    printf("%s\n\n\n\n",heads);

    HINTERNET hRequest2 = HttpOpenRequest(hConnect, "POST","/", NULL, NULL, accept, 0, 0);
    //ERROR_INSUFFICIENT_BUFFER (122) with "accept".

    send=HttpSendRequest(hRequest2, hdrs, strlen(hdrs), frmdata,strlen(frmdata));
    if(!send){
        printf("HttpSendRequest failed, code=%d",GetLastError());
        system("pause>nul");
        return 0;
    }

    heads=getheaders(hRequest);
    printf("%s\n\n\n\n",heads);

    InternetCloseHandle(hRequest);
    InternetCloseHandle(hRequest2);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hSession);

    system("pause>nul");
    return 0;
}

【问题讨论】:

  • 你为什么要提出两个请求?我不知道 pastebin 的细节,但你可能应该只是发出 POST 请求。另外,我真的怀疑你应该发布到根目录。 GetLastError() 代码仅在函数失败时才有意义。您似乎正确地使用了 Content-Type 和表单数据。
  • 我试过只做一个 POST,但没用。我认为我可能需要先从网站获取 cookie 或标头。使用 Chrome 找出它如何使用 POST 和 GET,它会从网站本身 GET,然后 POST 到 /post.php,我也尝试过。
  • 这是在他们的网页上发布时通过网络发送的内容 (pastebin.com/qjLbBt9H);它使用的是 multipart/form-data 格式。
  • 自从您上一篇文章以来,我一直在使用数据包嗅探器 (Wireshark) 来查看浏览器所做的事情与我所做的事情相比有何不同。到目前为止,结果仍然是“您无法创建空粘贴。”。我认为这是因为表单数据之前的代码每次都会更改。 "-----WebKitFormBoundary________________"
  • 是的,即使通过 WinINet 发布看似相同的数据,我也会得到同样的结果。也许他们在服务器端做了一些鬼鬼祟祟的事情......

标签: c++ visual-studio forms wininet


【解决方案1】:

您的代码几乎是正确的,您必须确保以下几点:

  1. char* hdrs="Content-Type: application/x-www-form-urlencoded"; 您必须确保从 POST 消息返回的对象的类型为 x-www-form-urlencodedJSON 。如果是 JSON 你 需要定义char* hdrs="Content-Type: application/json\r\n"; 注意:您必须将\r\n 附加到 hdrs。

  2. 例如尝试使用大小为 10000 的缓冲区调用 readFile 方法 和打印缓冲区,它会将响应的输出打印到 连接

  3. HINTERNET hRequest2 = HttpOpenRequest(hConnect, "POST","/", NULL, NULL, accept, 0, 0); 而不是“/”中,您必须调用 请求的 API 例如:.
    HINTERNET hRequest2 = HttpOpenRequest(hConnect, "POST", "/users/jsonlogin", NULL, NULL, accept, 0, 0);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 2012-03-15
    • 1970-01-01
    相关资源
    最近更新 更多