HttpSendRequest-POST数据不支持Unicode 我正在研究一种C++代理,它将使用HTTPSeDebug请求()将信息(例如系统主机名)回放到中央服务器上。我想让它发回的信息之一是操作系统。我创建了以下函数来获取系统主机名 wstring getOS() { HKEY key; RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &key); // Obtains Registry handle DWORD type; wchar_t buffer[MAX_PATH]; // MAX_PATH = 260 - The system hostname should never exceed this value DWORD size = sizeof(buffer); RegQueryValueEx(key, L"ProductName", NULL, &type, (LPBYTE)&buffer, &size); // Queries Registry key - stores value in "buffer" wstring os(buffer); // Converts from C-style character array to wstring return os; // Returns wstring to caller }
此函数将使用注册表获取操作系统,并将其存储为wstring。然后,我想将返回的“os”wstring传递给下面的post()函数,但我注意到,对于HTTP post数据,必须使用字符串而不是wstring。下面是my post()函数的代码:HttpSendRequest-POST数据不支持Unicode 我正在研究一种C++代理,它将使用HTTPSeDebug请求()将信息(例如系统主机名)回放到中央服务器上。我想让它发回的信息之一是操作系统。我创建了以下函数来获取系统主机名 wstring getOS() { HKEY key; RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &key); // Obtains Registry handle DWORD type; wchar_t buffer[MAX_PATH]; // MAX_PATH = 260 - The system hostname should never exceed this value DWORD size = sizeof(buffer); RegQueryValueEx(key, L"ProductName", NULL, &type, (LPBYTE)&buffer, &size); // Queries Registry key - stores value in "buffer" wstring os(buffer); // Converts from C-style character array to wstring return os; // Returns wstring to caller },c++,unicode,C++,Unicode,此函数将使用注册表获取操作系统,并将其存储为wstring。然后,我想将返回的“os”wstring传递给下面的post()函数,但我注意到,对于HTTP post数据,必须使用字符串而不是wstring。下面是my post()函数的代码: void post() { HINTERNET hInternetOpen = InternetOpen(userAgent.c_str(), INTERNET_OPEN_TYPE_PROXY, L"http://127.0.0.1:9999",
void post()
{
HINTERNET hInternetOpen = InternetOpen(userAgent.c_str(), INTERNET_OPEN_TYPE_PROXY, L"http://127.0.0.1:9999", NULL, 0);
HINTERNET hInternetConnect = InternetConnect(hInternetOpen, host.c_str(), INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
HINTERNET hHttpOpenRequest = HttpOpenRequest(hInternetConnect, L"POST", file.c_str(), NULL, NULL, NULL, 0, 0);
wstring headers = L"Content-Type: application/x-www-form-urlencoded"; // Content-Type is necessary to POST
string postData = "os="; // Why does this have to be a string and not a wstring?
HttpSendRequest(hHttpOpenRequest, headers.c_str(), headers.length(), (LPVOID)postData.c_str(), postData.size());
InternetCloseHandle(hInternetOpen);
InternetCloseHandle(hInternetConnect);
InternetCloseHandle(hHttpOpenRequest);
}
如果我尝试将“postData”设置为wstring,我会得到如下图所示的内容:
有人能解释一下将wstring作为POST数据的最简单方法吗?HttpSendRequest()
只知道原始字节,而不知道字符串。您可以使用std::wstring
发送UTF-16数据,但必须通过内容类型
标题中的字符集
属性告诉服务器您正在发送UTF-16
wstring headers = L"Content-Type: application/x-www-form-urlencoded; charset=utf-16";
// TODO: don't forget to URL-encode the value from getOS() to
// escape reserved characters, including '=' and '&'...
wstring postData = L"os=" + getOS();
HttpSendRequest(hHttpOpenRequest, headers.c_str(), headers.length(),
postData.c_str(), postData.length() * sizeof(wchar_t));
注意上面使用的sizeof(wchar\t)
。在屏幕截图中,您的嗅探器显示的是原始数据,它显示的数据是UTF-16的样子,但是您只看到了wstring
数据的一半,因为您正在将HttpSendRequest()
的dwOptionalLength
参数设置为字符计数(7),而不是字节计数(14):
dwOptionalLength[in]可选数据的大小,以字节为单位。如果没有要发送的可选数据,则此参数可以为零 使用
std::string
时,字符计数和字节计数是相同的值
您真正应该发送的是UTF-8而不是UTF-16,例如:
string Utf8Encode(const wstring &wstr)
{
// NOTE: C++11 has built-in support for converting between
// UTF-8 and UTF-16. See the std::wstring_convert class...
/*
wstring_convert<codecvt_utf8_utf16<wchar_t>> conv;
return conv.to_bytes(wstr);
*/
string out;
int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL);
if (len > 0)
{
out.resize(len);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), &out[0], len, NULL, NULL);
}
return out;
}
HttpSendRequest()
只知道原始字节,不知道字符串。您可以使用std::wstring
发送UTF-16数据,但必须通过内容类型
标题中的字符集
属性告诉服务器您正在发送UTF-16
wstring headers = L"Content-Type: application/x-www-form-urlencoded; charset=utf-16";
// TODO: don't forget to URL-encode the value from getOS() to
// escape reserved characters, including '=' and '&'...
wstring postData = L"os=" + getOS();
HttpSendRequest(hHttpOpenRequest, headers.c_str(), headers.length(),
postData.c_str(), postData.length() * sizeof(wchar_t));
注意上面使用的sizeof(wchar\t)
。在屏幕截图中,您的嗅探器显示的是原始数据,它显示的数据是UTF-16的样子,但是您只看到了wstring
数据的一半,因为您正在将HttpSendRequest()
的dwOptionalLength
参数设置为字符计数(7),而不是字节计数(14):
dwOptionalLength[in]可选数据的大小,以字节为单位。如果没有要发送的可选数据,则此参数可以为零 使用
std::string
时,字符计数和字节计数是相同的值
您真正应该发送的是UTF-8而不是UTF-16,例如:
string Utf8Encode(const wstring &wstr)
{
// NOTE: C++11 has built-in support for converting between
// UTF-8 and UTF-16. See the std::wstring_convert class...
/*
wstring_convert<codecvt_utf8_utf16<wchar_t>> conv;
return conv.to_bytes(wstr);
*/
string out;
int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL);
if (len > 0)
{
out.resize(len);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), &out[0], len, NULL, NULL);
}
return out;
}
为什么你说“必须使用字符串而不是wstring”?如果我尝试使用wstring而不是字符串,它会弄乱POST数据(请参阅随附的屏幕截图)。你希望通过网络发送什么?utf8?请参见此处
size()
返回字符串中的字符数,而不是它们占用的内存量。如果您在wstring
上调用size()
,就像在代码中当前使用的string
上一样,那么您就做错了。@captain不经意地感谢您,我已将其改为使用.length()而不是.size()。为什么您说“必须使用string而不是wstring”?如果我尝试使用wstring而不是string,它会弄乱POST数据(见附件屏幕截图)。您希望通过网络发送什么?utf8?请参见此处size()
返回字符串中的字符数,而不是它们占用的内存量。如果您在wstring
上调用size()
,就像您在代码中当前使用的字符串上一样,那么您就做错了。@captain不经意的谢谢您,我已将它改为使用.length()而不是.size()。您就是那个人!这是可行的,应该是公认的答案。如果我有足够的声誉,我会投票给它的:/非常感谢你!我只是点击了复选标记。如果这不起作用,请告诉我。再次感谢你,你就是那个男人!这是可行的,应该是公认的答案。如果我有足够的声誉,我会投票给它的:/非常感谢你!我只是点击了复选标记。如果这不起作用,请告诉我。再次感谢。