我正在嘗試在 Linux 上使用套接字執行 HTTP 請求,我的函式現在可以作業,但只能使用簡單的域作為www.google.com或webpage.000webhostapp.com。當我嘗試添加路徑和查詢時webpage.000webhostapp.com/folder/file.php?parameter=value,它開始失敗。
這是我的代碼:
#include <iostream>
#include <cstring>
#include <string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
int main(){
int socket_desc;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[4096];
std::string url = "www.exampleweb.com/folder/file.php";
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if(socket_desc < 0){
std::cout<<"failed to create socket"<<std::endl;
}
server = gethostbyname(url.c_str());
if(server==NULL){std::cout<<"could Not resolve hostname :("<<std::endl;}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(80);
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
if(connect(socket_desc, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
std::cout<<"connection failed :("<<std::endl;
}
std::string request = "GET / HTTP/1.1\r\nHost: " url "\r\nConnection: close\r\n\r\n";
if(send(socket_desc, request.c_str(), strlen(request.c_str()) 1, 0) < 0){
std::cout<<"failed to send request..."<<std::endl;
}
int n;
std::string raw_site;
while((n = recv(socket_desc, buffer, sizeof(buffer) 1, 0)) > 0){
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r'){
raw_site =buffer[i];
i = 1;
}
}
std::cout<<raw_site<<std::endl;
return 0;
}
使用www.google.com,它非常適合請求。
使用www.example.com/folder/file.php?parameter=value¶meter2=value2,它失敗并回傳"could not resolve hostname"。
關于如何修復它的任何想法?
我沒有使用 curl,也不能在這個專案中使用它。
uj5u.com熱心網友回復:
gethostbyname()(順便說一句,不推薦使用,您應該getaddrinfo()改用)不適用于 URL,僅適用于主機名。
給定一個像 的 URL http://www.exampleweb.com/folder/file.php?parameter=value¶meter2=value2,你需要先把它分解成它的組成部分(閱讀RFC 3986),例如:
- 方案
http - 主機名
www.exampleweb.com - 資源路徑
/folder/file.php - 查詢
?parameter=value¶meter2=value2
然后您可以決議主機的 IP 地址,在埠 80(HTTP 的默認埠)上連接到該 IP 地址,因為 URL 沒有指定不同的埠,最后發送GET對資源和查詢的請求。
另請注意,請求中的Host標頭GET必須僅指定主機名(和埠,如果與默認值不同),而不是整個 URL。而且 HTTP 請求不是空終止字串,所以不要發送空終止符。閱讀RFC 2616。
試試這個:
#include <iostream>
#include <cstring>
#include <string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
int main(){
int socket_desc;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[4096];
std::string host = "www.exampleweb.com";
std::string port = "80";
std::string resource = "/folder/file.php";
std::string query = "?parameter=value¶meter2=value2";
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0){
std::cout << "failed to create socket" << std::endl;
return 0;
}
server = gethostbyname(host.c_str());
if (server == NULL){
std::cout << "could Not resolve hostname :(" << std::endl;
close(socket_desc);
return 0;
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(std::stoi(port));
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
if (connect(socket_desc, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
std::cout << "connection failed :(" << std::endl;
close(socket_desc);
return 0;
}
std::string request = "GET " resource query " HTTP/1.1\r\nHost: " host "\r\nConnection: close\r\n\r\n";
if (send(socket_desc, request.c_str(), request.size(), 0) < 0){
std::cout << "failed to send request..." << std::endl;
close(socket_desc);
return 0;
}
int n;
std::string raw_site;
while ((n = recv(socket_desc, buffer, sizeof(buffer), 0)) > 0){
raw_site.append(buffer, n);
}
close(socket_desc);
std::cout << raw_site << std::endl;
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/401706.html
