您好我正在编写一个简单的C程序,通过套接字向服务器发送请求
它将一个字符串发送到套接字槽send()函数,然后显示recv()
获取的结果如果我通过端口80上的telnet连接,我可以输入:
GET /index.html HTTP/1.0
然后插入两个换行符,我得到我的html页面。
如果我执行 HEAD 而不是 GET ,则会显示横幅。
我无法在我的程序中重新演绎此行为,服务器始终响应,就好像是 HEAD 请求,即我发送 GET 请求并获得横幅而不是HTML页面。我不知道它有什么问题。我确定请求是在我输入时发送的,因为我正在记录它..
使用完整程序代码更新
const char DEFAULT_REQUEST[] = "GET /index.html HTTP/1.0";
int main (int argc, char* argv[])
{
char finalRequest[200];
char* request = (char*)DEFAULT_REQUEST;
if (argc < 3)
{
if (argc < 2)
{
printf("Usage: %s <hostname> <request>\n", argv[0]);
exit(1);
}
log_warn("DEFAULT REQUEST \"%s\"", DEFAULT_REQUEST);
} else request = argv[2];
sprintf(finalRequest, "%s%s%s", request, EOL, EOL);
log_info("HOST: %s", argv[1]);
//RESOLVE HOST
struct hostent *host_info = gethostbyname(argv[1]);
check(host_info != NULL, "Looking up hostname");
//CREATE SOCKET
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
check(socket_fd > -1, "Setting up socket");
//SETUP ADDRESS
struct sockaddr_in tareget_addr;
tareget_addr.sin_family = AF_INET;
tareget_addr.sin_addr = *((struct in_addr *) host_info->h_addr);
tareget_addr.sin_port = htons(80);
memset(&(tareget_addr.sin_zero), '\0', 8);
//CONNECT SOCKET
int conn_res = connect(socket_fd, (struct sockaddr *) &tareget_addr, sizeof(struct sockaddr));
check(conn_res > -1, "Connecting socket to target");
//SEND REQUEST
send_string(socket_fd, finalRequest);
log_info("Request sent: %s\n", finalRequest);
//PRINT RESULT
const int recv_buff_size = 512;
char recv_buffer[recv_buff_size];
while (1)
{
int bytes_read = recv(socket_fd, recv_buffer, recv_buff_size, 0);
if (bytes_read <= 0) break;
printf("%s", recv_buffer);
}
close(socket_fd);
return 0;
}
正如您所看到的,我使用的两个EOL等于 \ r \ n \ r \ n
只有 \ r \ n \ r
才能正常工作不能仅使用 \ r \ n
只有 \ n 或 \ n \ n
的Segfaults答案 0 :(得分:2)
由于我的评论似乎没有帮助过你,我把一个粗略的控制台程序放在一起来展示这个过程。 (Gawd - 我忘记了c ++字符串比c风格的字符串有多少改进)
您没有提及操作系统(考虑到查询的性质,您不会提及),所以我使用win32套接字和win32程序完成了它。
首先,输出:
Performing a HEAD request
-------
HTTP headers for 'http://www.example.com'
-------
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: max-age=604800
Content-Type: text/html
Date: Thu, 19 Feb 2015 11:57:18 GMT
ETag: "359670651"
Expires: Thu, 26 Feb 2015 11:57:18 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (cpm/F9D5)
X-Cache: HIT
x-ec-custom-error: 1
Content-Length: 1270
X-Cache: MISS from tx33vspep26a
Connection: close
Performing a GET request
-------
HTTP headers for 'http://www.example.com'
-------
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: max-age=604800
Content-Type: text/html
Date: Thu, 19 Feb 2015 11:57:19 GMT
ETag: "359670651"
Expires: Thu, 26 Feb 2015 11:57:19 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (cpm/F9D5)
X-Cache: HIT
x-ec-custom-error: 1
Content-Length: 1270
X-Cache: MISS from tx33vspep26a
Connection: close
HTTP content for 'http://www.example.com'
-------
<!doctype html>
<html>
<head>
<title>Example Domain</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
div {
width: 600px;
margin: 5em auto;
padding: 50px;
background-color: #fff;
border-radius: 1em;
}
a:link, a:visited {
color: #38488f;
text-decoration: none;
}
@media (max-width: 700px) {
body {
background-color: #fff;
}
div {
width: auto;
margin: 0 auto;
border-radius: 0;
padding: 1em;
}
}
</style>
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is established to be used for illustrative examples in documents. You may use this
domain in examples without prior coordination or asking for permission.</p>
<p><a href="http://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
最后,产生它的代码(不要忘记链接到ws2_32 lib)
如果取消注释mGetHeaders
中紧接在步骤4之前的行,您可以看到请求字符串的格式与我之前在评论中提到的一样。
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
void mParseUrl(char *mUrl, char **serverName, char **filepath, char **filename)
{
int n;
char *tmpUrl;
if (strcmpi(mUrl, "http://") != 0)
tmpUrl = strdup( mUrl + 7);
else if (strcmpi(mUrl, "https://") != 0)
tmpUrl = strdup( mUrl + 8);
char *slashPos, *lastSlashPos;
slashPos = strchr(tmpUrl, '/');
if (slashPos != NULL)
{
*serverName = (char*)calloc(slashPos - tmpUrl + 1, 1);
strncpy(*serverName, tmpUrl, slashPos-tmpUrl);
lastSlashPos = strrchr(filepath, '/');
*filename = strdup(lastSlashPos+1);
}
else
{
*serverName = strdup(tmpUrl);
*filepath = strdup("/");
*filename = strdup("");
}
free(tmpUrl);
}
SOCKET connectToServer(char *szServerName, WORD portNum)
{
struct hostent *hp;
unsigned int addr;
struct sockaddr_in server;
SOCKET conn;
conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (conn == INVALID_SOCKET)
return NULL;
if(inet_addr(szServerName)==INADDR_NONE)
{
hp=gethostbyname(szServerName);
}
else
{
addr=inet_addr(szServerName);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
return NULL;
}
server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
server.sin_family=AF_INET;
server.sin_port=htons(portNum);
if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
{
closesocket(conn);
return NULL;
}
return conn;
}
char *mGetHeaders(char *szUrl)
{
// string server, filepath, filename;
char *serverName, *filepath, *filename;
int portNum = 80;
const int bufSize = 512;
char sendBuffer[bufSize];
char tmpBuffer[bufSize];
char receiveBuffer[bufSize];
char *result = NULL;
SOCKET conn;
long thisReadSize, totalBytesRead;
// 1 - parse url into seperate components
mParseUrl(szUrl, &serverName, &filepath, &filename);
// 2 - aquire a connection
conn = connectToServer( serverName, portNum);
// 3 - send a request for the headers of the url
sprintf(tmpBuffer, "HEAD %s HTTP/1.0\r\n", szUrl);
strcpy(sendBuffer, tmpBuffer);
sprintf(tmpBuffer, "HOST: %s\r\n", serverName );
strcat(sendBuffer, tmpBuffer);
// sprintf(tmpBuffer, "User-Agent: %s\r\n", "mUserAgent_0.0.1");
// strcat(sendBuffer, tmpBuffer);
sprintf(tmpBuffer, "\r\n");
strcat(sendBuffer, tmpBuffer);
send(conn, sendBuffer, strlen(sendBuffer), 0);
// printf("Send Buffer: \n%s\n", sendBuffer);
// 4 - get received bytes
totalBytesRead = 0;
while(1)
{
memset(receiveBuffer, 0, bufSize);
thisReadSize = recv (conn, receiveBuffer, bufSize, 0);
if ( thisReadSize <= 0 )
break;
result = (char*)realloc(result, thisReadSize+totalBytesRead);
memcpy(result+totalBytesRead, receiveBuffer, thisReadSize);
totalBytesRead += thisReadSize;
}
result = (char*)realloc(result, totalBytesRead+1);
result[totalBytesRead] = NULL;
closesocket(conn);
free(serverName);
free(filepath);
free(filename);
return result;
}
int getHeaderLength(char *content)
{
const char *srchStr1 = "\r\n\r\n", *srchStr2 = "\n\r\n\r";
char *findPos;
int ofset = -1;
findPos = strstr(content, srchStr1);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr1);
}
else
{
findPos = strstr(content, srchStr2);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr2);
}
}
return ofset;
}
char *readUrl2(char *szUrl, long *bytesReturnedOut, char **headerOut)
{
const int bufSize = 512;
char readBuffer[bufSize], sendBuffer[bufSize], tmpBuffer[bufSize];
char *tmpResult=NULL, *result;
SOCKET conn;
// string server, filepath, filename;
char *serverName, *filepath, *filename;
long totalBytesRead, thisReadSize, headerLen;
// mParseUrl(szUrl, server, filepath, filename);
mParseUrl(szUrl, &serverName, &filepath, &filename);
///////////// step 1, connect //////////////////////
conn = connectToServer(serverName, 80);
///////////// step 2, send GET request /////////////
sprintf(tmpBuffer, "GET %s HTTP/1.0", filepath);
strcpy(sendBuffer, tmpBuffer);
strcat(sendBuffer, "\r\n");
sprintf(tmpBuffer, "Host: %s", serverName);
strcat(sendBuffer, tmpBuffer);
strcat(sendBuffer, "\r\n");
strcat(sendBuffer, "\r\n");
send(conn, sendBuffer, strlen(sendBuffer), 0);
///////////// step 3 - get received bytes ////////////////
// Receive until the peer closes the connection
totalBytesRead = 0;
while(1)
{
memset(readBuffer, 0, bufSize);
thisReadSize = recv (conn, readBuffer, bufSize, 0);
if ( thisReadSize <= 0 )
break;
tmpResult = (char*)realloc(tmpResult, thisReadSize+totalBytesRead);
memcpy(tmpResult+totalBytesRead, readBuffer, thisReadSize);
totalBytesRead += thisReadSize;
}
headerLen = getHeaderLength(tmpResult);
long contentLen = totalBytesRead-headerLen;
result = (char*)calloc(contentLen+1, 1); //new char[contenLen+1];
memcpy(result, tmpResult+headerLen, contentLen);
result[contentLen] = 0x0;
char *myTmp;
myTmp = (char*)calloc(headerLen+1, 1); //new char[headerLen+1];
strncpy(myTmp, tmpResult, headerLen);
myTmp[headerLen] = NULL;
free(tmpResult);
*headerOut = myTmp;
*bytesReturnedOut = contentLen;
closesocket(conn);
return(result);
}
int main()
{
WSADATA wsaData;
const char *soUrl = "http://www.example.com";
if ( WSAStartup(0x101, &wsaData) != 0)
return -1;
printf("Performing a HEAD request\n");
printf("-------\n");
char *soHeaders = mGetHeaders(soUrl);
printf("HTTP headers for '%s'\n", soUrl);
printf("-------\n");
printf("%s\n", soHeaders);
free(soHeaders);
long nBytesRetrived;
char *responseHeader;
printf("Performing a GET request\n");
printf("-------\n");
char *soContent = readUrl2(soUrl, &nBytesRetrived, &responseHeader);
printf("HTTP headers for '%s'\n", soUrl);
printf("-------\n");
printf("%s\n", responseHeader);
free(soHeaders);
printf("HTTP content for '%s'\n", soUrl);
printf("-------\n");
printf("%s\n", soContent);
free(soContent);
WSACleanup();
return 0;
}