【问题标题】:POST Winsock troublePOST Winsock 麻烦
【发布时间】:2014-01-27 10:55:01
【问题描述】:

现在我开始研究插座。但它不能用我的手正常工作。我有很酷的登录方法:

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)

请帮忙,谢谢。

【问题讨论】:

    标签: c++ winsock2


    【解决方案1】:
    int BytesSent = send(MySocket, Buffer, sizeof(Buffer), 0);
    

    这发送了太多字节的数据,在请求结束时留下一大堆垃圾,它认为是下一个请求的一部分。

    string data = "login=" + name + "&password=" + password;
    

    这个查询最后没有&amp;

    "password=%s&", data.length(), name.c_str(), password.c_str());
    

    这会将&amp; 放在查询的末尾。嗯,是哪个?

    你需要解决两件事:

    1. 查询结尾处的&amp; 保持一致。 (为什么你还要写两次查询字符串?)

    2. 使用strlen(Buffer) 而不是sizeof(Buffer)

    实际上,您应该使用实际协议规范的实现,而不是这样的代码。例如,如果密码中有&amp;,会发生什么情况?如果服务器决定在回复中使用分块编码会发生什么?您实际上并没有实现 HTTP 1.1,但您声称自己实现了。这迟早会导致很多很多的痛苦。

    【讨论】:

      【解决方案2】:

      您发送的字节过多,您没有正确格式化 POST 消息的正文,并且您根本没有正确读取响应。

      如果您打算使用 C++ 进行某些字符串处理,那么您应该使用 C++ 进行所有字符串处理,如果可以的话,请避免混合使用 C 字符串处理。

      试试类似的方法:

      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.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: gzipConnection: Keep-Alive 标头,它们对响应处理有很大影响. 阅读RFC 2616 Section 4.4了解如何确定响应长度和格式的详细信息。

      话虽如此,HTTP 并不是一个可以手动实现的简单协议,因此您确实应该使用预制的 HTTP 库,例如 libcurl,或者使用 Microsoft 自己的 WinInet 或 WinHTTP API。

      【讨论】:

      • 谢谢,正在尝试使用winhttp
      猜你喜欢
      • 1970-01-01
      • 2010-11-11
      • 2011-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多