使用winsock发送POST数据(并使用PHP服务器端脚本接收它们)

时间:2011-08-02 15:40:54

标签: c++ http post winsock

所以我想我会尝试使用HTTP,并尝试将简单的普通(未编码)文本从我的程序发送到服务器。但是,有些事情是不对的,我不知道是什么。

这是服务器端的PHP脚本,我已经通过从HTML表单发送POST数据进行了测试,它运行得很好,所以我猜服务器端没有任何问题。

<?php
$file = 'postData.txt'; 
$somecontent = $_POST['dat'];
$fp = fopen($file, 'w') or die('Could not open file!');   
fwrite($fp, "$somecontent") or die('Could not write to file');  
fclose($fp);  
?>

这是程序(这段代码包括一些未使用的部分,比如在缓冲区中读取文件内容等等,这就是我一直在玩它并且每隔5秒更换一次东西,不介意):

#include <windows.h>
#include "WinSock2.h"
#include <stdio.h>
#include <stdint.h>
#include <iostream>
int main()
{
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    return 0;

SOCKET fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0)     throw;
SOCKADDR_IN service;
service.sin_family = AF_INET;
service.sin_port = htons(80);
LPHOSTENT host = gethostbyname("123.17.25.123");
if (!host)          throw;
service.sin_addr = *((LPIN_ADDR)*host->h_addr_list);
if (connect(fd, (SOCKADDR *)&service, sizeof(service)) < 0)     throw;
FILE *f = fopen("file.txt", "rb");
if (!f)         throw;
uint32_t len = 0;
fseek(f, 0x00, SEEK_END);
len = ftell(f);
fseek(f, 0x00, SEEK_SET);
char header[1024];
char *buffer = new char[len];
fread(buffer, sizeof(char), len, f);
sprintf(header,
        "POST /recv.php HTTP/1.1\r\n"
        "Host: 123.17.25.123\r\n"
        "User-Agent: Mozilla Firefox/4.0\r\n"
        "Content-Length: %d\r\n"
        "Content-Type: application/x-www-form-urlencoded\r\n"
        "Accept-Charset: utf-8\r\n\r\n",
        len+4);
std::cout << header << std::endl;
send(fd, header, strlen(header), 0);
send(fd, "dat=", 4, 0);
send(fd, buffer, strlen(buffer), 0);
send(fd, "\r\n", 2, 0);
delete [] buffer;
fprintf(stderr, "Done\n");
closesocket(fd);
WSACleanup();
return 0;
}

那么,它有什么问题?有谁有想法吗? :P

edit1:我使用wireshark监控流量并尝试运行该程序几次,但没有捕获数据包。奇怪的是,它甚至没有发送任何东西。

edit2:感谢TokenMacGuy让它发挥作用。上面的代码是蹩脚的,但它会读取所有文件内容并将其作为POST数据发送到您的服务器,希望它对像我这样的新手学习有用。再次感谢你!

2 个答案:

答案 0 :(得分:1)

POST应该在数据之前有两个换行符,而不是在它之后。

    "Accept-Charset: utf-8\r\n\r\n"
    "dat=somedata\r\n",

答案 1 :(得分:1)

您没有收到数据,因为您实际上并未发送任何数据。虽然buffer中出现sprintf,但没有格式说明符可供使用(只有格式化长度)。

尝试完全从sprintf调用中删除buffer,然后两次调用send,一次调用标题(如您所做),然后再次发送实际数据。

或许您不打算从您阅读的文件中发送任何数据。你只想得到dat=somedatar。问题是您将内容类型指定为text/plain,在这种情况下,服务器根本不会解释它。内容类型可能应为application/x-www-form-urlencoded。由于dat参数是正文的一部分,因此content-length标题必须包含它。如果内容长度与作为内容发送的实际字节数不匹配,符合要求的服务器将忽略整个请求(通常返回400-499范围的响应代码)。