我正在学习在OS X机器上使用C和C ++中的本机套接字。在之前的项目中,我在http://castifyreceiver.com/index.html设置了一个非常简单的网页。这个网页几乎没有任何作用,所以我不介意分享真实的网址。
基本上我的问题是我的所有HTTP请求都返回400 Bad Request。我知道我用于此练习的网页已启动并运行,我可以通过浏览器访问它。这让我相信我正在错误地实施HTTP协议,但我不知道我哪里出错了。
以下是我用来通过套接字请求此页面的所有代码。
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
int main(int argc, const char * argv[]) {
// create the request
const char * request = "GET /index.html HTTP/1.1\nAccept: */*\n\n";
size_t length = strlen(request);
printf("request:\n\n%s", request);
// get the destination address
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
struct addrinfo * address;
getaddrinfo("castifyreceiver.com", "http", &hints, &address);
// create a socket
int sfd = socket(address->ai_family, address->ai_socktype, address->ai_protocol);
int result = connect(sfd, address->ai_addr, address->ai_addrlen);
if (result != 0) {
printf("connection failed: %i\n", result);
freeaddrinfo(address);
close(sfd);
return 0;
} else {
printf("connected\n");
}
// write to socket
ssize_t written = write(sfd, request, length);
printf("wrote %lu of %lu expected\n", written, length);
// read from socket and cleanup
char response[4096];
ssize_t readed = read(sfd, response, 4096);
printf("read %lu of 4096 possible\n", readed);
close(sfd);
freeaddrinfo(address);
// display response message
response[readed] = '\0';
printf("response:\n\n%s\n", response);
return 0;
}
该程序始终输出类似于以下内容的内容:
request:
GET /index.html HTTP/1.1
Accept: */*
connected
wrote 38 of 38 expected
read 590 of 4096 possible
response:
HTTP/1.1 400 Bad Request
Date: Thu, 05 Nov 2015 18:24:08 GMT
Server: Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/1.0.1e-fips mod_bwlimited/1.4
Content-Length: 357
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand. <br />
</p>
<hr>
<address>Apache/2.2.31 (Unix) mod_ssl/2.2.31 OpenSSL/1.0.1e-fips mod_bwlimited/1.4 Server at 108.167.131.50 Port 80</address>
</body></html>
我花了很多时间查看RFC 2616,但仍然无法找到我做错的事情。任何帮助表示赞赏。
答案 0 :(得分:3)
两件事:
您必须发送Host
标题,参见RFC 2616 p。 129:
客户端必须在所有HTTP / 1.1请求中包含Host头字段 消息。如果请求的URI不包含Internet主机 要请求的服务的名称,然后主机头字段必须 给出一个空值。
使用\r\n
在HTTP中终止您的行,而不仅仅是\n
,参见RFC 2616 p。 16:
HTTP / 1.1将序列CR LF定义为所有的行尾标记 除实体主体外的协议要素(见附录19.3) 宽容的申请)。实体主体内的行尾标记 由相关的媒体类型定义,如3.7节所述。
如果你改变它,它应该有效。