POST Winsock麻烦
现在我开始研究套接字了。但是我的双手无法正常工作。我有很酷的登录方法:POST Winsock麻烦
int LogIn(const string &name, const string &password)
{
char Buffer[1024];
string data = "login=" + name + "&password=" + password;
sprintf(Buffer, "POST /Test/login_cl.php HTTP/1.1\r
"\nContent-Length: %d\r"
"\nConnection: Keep-Alive\r"
"\nAccept-Encoding: gzip\r"
"\nAccept-Language: ru-RU,en,*\r"
"\nUser-Agent: Mozilla/5.0\r"
"\nHost: 127.0.0.1\r"
"\nContent-Type: application/x-www-form-urlencoded\r\n\r\n"
"login=%s&"
"password=%s&", data.length(), name.c_str(), password.c_str());
int BytesSent = send(MySocket, Buffer, sizeof(Buffer), 0);
string test;
char ans;
while (recv(MySocket, &ans, 1, 0))
test.push_back(ans);
cout << test << endl;
return 0;
}
问题是我只能调用一次这个方法。其他来电或注销方法调用不工作,例如:
int result = LogIn(logn, paswd);
int result = LogIn(logn, paswd);
不工作,我得到的答案只有一个(第二个是空的和recv将返回-1)
请帮忙,谢谢。
int BytesSent = send(MySocket, Buffer, sizeof(Buffer), 0);
这发出了太多字节的数据,让对方用在它认为是下一个请求的一部分,请求结束一大堆垃圾。
string data = "login=" + name + "&password=" + password;
这个查询没有&
最后。
"password=%s&", data.length(), name.c_str(), password.c_str());
这会在查询的末尾添加一个&
。那么,这是什么?
您需要解决两件事情:
是大致
&
上查询的结束一致。 (为什么要编写查询字符串两次呢?)使用
strlen(Buffer)
而不是sizeof(Buffer)
。
真的,应该使用实际协议规范的实现,而不是像这样的代码。例如,如果密码中有&
会发生什么情况?如果服务器决定在回复中使用分块编码会发生什么?你实际上并没有实现HTTP 1.1,但你声称你是这样做的。迟早会导致很多很多的痛苦。
您发送的字节太多,您没有正确格式化POST消息的正文,而且您根本没有正确读取响应。
如果您打算使用C++进行某些字符串处理,那么您应该使用C++来处理所有字符串,避免混淆C字符串处理。
尝试一些更喜欢这个:
const string SafeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz*-._";
string Urlencode(const string &str)
{
if (str.length() == 0)
return string();
ostringstream buffer;
for (int I = 0; I < ASrc.length(); ++I)
{
char ch = ASrc[I];
if (ch == ' ')
buffer << '+';
else if (SafeChars.find(ch) != string::npos)
buffer << ch;
else
buffer << '%' << setw(2) << fillchar('0') << hex << ch;
}
return buffer.str();
}
int LogIn(const string &name, const string &password)
{
string data = "login=" + Urlencode(name) + "&password=" + Urlencode(password);
ostringstream buffer;
buffer << "POST /Test/login_cl.php HTTP/1.1\r\n"
<< "Content-Length: " << data.length() << "\r\n"
<< "Connection: Keep-Alive\r\n"
<< "Accept-Encoding: gzip\r\n"
<< "Accept-Language: ru-RU,en,*\r\n"
<< "User-Agent: Mozilla/5.0\r\n"
<< "Host: 127.0.0.1\r\n"
<< "Content-Type: application/x-www-form-urlencoded\r\n"
<< "\r\n"
<< data;
string request = buffer.str();
const char *req = request.c_str();
int reqlen = request.length();
do
{
int BytesSent = send(MySocket, request.c_str(), request.length(), 0);
if (BytesSent <= 0)
return -1;
req += BytesSent;
reqlen -= BytesSent;
}
while (reqlen > 0);
// you REALLY need to flesh out this reading logic!
// See RFC 2616 Section 4.4 for details
string response;
char ch;
while (recv(MySocket, &ch, 1, 0) > 0)
response += ch;
cout << response << endl;
return 0;
}
我会离开它作为一个练习,你学习阅读的HTTP响应(提示的正确方法:it is a LOT harder then you think - 尤其是因为你是包括Accept-Encoding: gzip
和Connection: Keep-Alive
这对响应处理有很大影响,请参阅RFC 2616 Section 4.4了解如何确定响应长度和格式)。这就是说,HTTP并不是一个手工实现的简单协议,所以你应该使用一个预制的HTTP库,比如libcurl,或者使用微软自己的WinInet或者WinHTTP APIs。
谢谢,现在试图使用winhttp –