POST Winsock trouble
POST Winsock trouble
现在我开始研究插座。但这无法与我的手一起正常工作。我有登录的酷方法:
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.1r
"nContent-Length: %dr"
"nConnection: Keep-Aliver"
"nAccept-Encoding: gzipr"
"nAccept-Language: ru-RU,en,*r"
"nUser-Agent: Mozilla/5.0r"
"nHost: 127.0.0.1r"
"nContent-Type: application/x-www-form-urlencodedrnrn"
"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,但您声称自己这样做。这将迟早会导致很多痛苦。
您发送的字节太多,您没有正确地格式化消息的主体,也无法正确阅读响应。
如果您要使用C 进行某些字符串处理,则应将C 用于所有字符串处理,请避免使用C String Crestling。
尝试更多这样的东西:
const string SafeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*-._";
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.1rn"
<< "Content-Length: " << data.length() << "rn"
<< "Connection: Keep-Alivern"
<< "Accept-Encoding: gziprn"
<< "Accept-Language: ru-RU,en,*rn"
<< "User-Agent: Mozilla/5.0rn"
<< "Host: 127.0.0.1rn"
<< "Content-Type: application/x-www-form-urlencodedrn"
<< "rn"
<< 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响应的正确方法(提示:它是一个 lot 更难的想法 - 尤其是因为您包括Accept-Encoding: gzip
和Connection: Keep-Alive
标头,对响应处理有很大影响。阅读RFC 2616第4.4节,以获取详细信息如何确定响应长度和格式)。
话虽如此,http不是手工实现的琐碎协议,因此您确实应该使用预制的http库,例如libcurl,或使用Microsoft自己的WinInet或Winhttp Apis。
相关文章:
- (Winsock) UDP 接收工作正常,但同一套接字的发送失败
- WinSock Non-Blocking I/O
- Boost.Asio/OpenSSL HTTPS GET certificate trouble
- 使用 winsock 接收 http 请求
- 如何查找 winsock.h 在 Visual Studio 中的包含位置
- 在Linux上交叉编译Windows应用程序时如何链接到Winsock?
- C++低吞吐量 winsock TCP 测试应用程序
- Winsock 数据不是从 IP 检索的,而是从普通 URL 检索的
- 错误:10035 Winsock发送
- 如何使用c++在winsock中从客户端向服务器发送大字符串
- 如何使用winsock在c++应用程序中实现安全套接字通信
- 如何为winsock的send()函数构造constchar*缓冲区
- C++WinSock选择本地接口进行连接
- 使用全局 IP 地址时,C++ winsock 2 应用程序中的代码是否必须更改?
- 使用 WinSock 处理多个用户
- Winsock本地客户服务器基准测试
- WinSock c++ inet_ntop始终显示 204.204.204.204(并且 accept() 没有失败)
- Winsock错误10022在听
- 致命错误:Winsock:没有这样的文件或目录
- POST Winsock trouble