挂断 HTTP Get/Request
Hang up on HTTP Get/Request
我不确定 where/how 我的程序挂断了。我非常有信心发送或接收链接......但即使在互联网上搜索了一些帮助并得到了我教授的帮助之后,我仍然迷失了,为什么这不起作用。
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define LENGTH 500
int main(int argc, char** argv)
{
// holds the value of the command-line argument
char link[LENGTH];
strcpy (link , argv[1]);
printf ("%s\n", link);
// break up link into the host and path -- use the "/"
char _host[LENGTH];
char _path[LENGTH];
int slashCount = 0;
int i;
for (i=0 ; i<strlen(link); i++)
{
printf ("%c , slashcount: %d\n", link[i], slashCount);
if (link[i] == '/') slashCount ++;
if (slashCount > 2)
{
// i is at the end of the host
strncpy (_host , link , i);
_host[i] = '[=11=]';
break;
}
} // end for
if (slashCount == 2)
{
// given only a host, copy the entire string into the host
strncpy(_host, link, i);
_host[i] = '[=11=]';
}
else // get the path for slashCount of 3
{
for (i ; strlen(link); i++ )
{
strcat (_path, &link[i]);
// if slash at the end of host name
if (strlen(_path) == 1)
{
// set the file field to be index.html
char t[11] = {'i','n','d','e','x','.','h','t','m','l','[=11=]'};
for (int c=0; c< 10 ; c++)
strncpy(_path, t, 11);
}
break;
}
} // end if/else
printf ("%s\n" , _host); /*success*/
printf ("%s\n" , _path); /*success*/
struct addrinfo hints;
struct addrinfo * result, * rp;
int sock_fd, s;
hints.ai_socktype = SOCK_STREAM;
memset(&hints,0,sizeof(struct addrinfo)); // setting the values to 0
s = getaddrinfo("::1","http", &hints,&result); ///////////////
if (0 != s)
{
perror("error populating address structure");
exit(1);
}
printf ("entering tcp setup connections");
// check the host name’s IP address — has a dynamic configuration(DNS)
// but does not change very frequently
for (rp = result; rp != NULL; rp = rp->ai_next)
{
sock_fd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sock_fd == -1)
continue;
if (connect(sock_fd, rp->ai_addr, rp->ai_addrlen) != -1)
break;
close(sock_fd);
}
if (rp == NULL)
{
// you didn’t find a good ip address to connect with
fprintf(stderr, "could not connect\n");
exit(1);
} // end for
freeaddrinfo(result);
// sending the request
sprintf (link, "GET %s HTTP/1.0\r\n" "Host: %s\r\n\r\n", _path, _host);
if (send (sock_fd, link, strlen(link), 0 )< 0)
fprintf (stderr, "Error with send\n");
else
fprintf (stderr, "Successfully send the fetch request\n");
// responding to the send
char buf[500];
memset(&buf,0,sizeof(buf));
/* int recv_count = recv(sock_fd, buf, 500, 0);
if(recv_count<0)
{
perror("Receive failed");
exit(1);
}
printf("%s",buf); */
/* while (0 > recv (sock_fd, buf, 500, 0))
{
printf ("%s", buf);
}
shutdown(sock_fd,SHUT_RDWR); */
exit (1);
}
明白了要发get请求,把response部分注释掉,看到有成功进入tcp连接设置。我只是对如何设置响应感到困惑。我知道如何使用 read/write,但我也想尝试 send/recv。
非常感谢任何帮助。
我目前得到的输出:
http://google.com/
h , slashcount: 0
t , slashcount: 0
t , slashcount: 0
p , slashcount: 0
: , slashcount: 0
/ , slashcount: 0
/ , slashcount: 1
g , slashcount: 2
o , slashcount: 2
o , slashcount: 2
g , slashcount: 2
l , slashcount: 2
e , slashcount: 2
. , slashcount: 2
c , slashcount: 2
o , slashcount: 2
m , slashcount: 2
/ , slashcount: 2
http://google.com
index.html
Successfully send the fetch request
entering tcp setup connections
recv()
的 return 值表示 Connection refused
,这表明套接字设置存在问题。
你需要把两行的顺序颠倒一下:
hints.ai_socktype = SOCK_STREAM;
memset(&hints,0,sizeof(struct addrinfo)); // setting the values to 0
以便您在 将内存设置为零后分配 ai_socktype
。
在 getaddrinfo()
调用中,从 cli 接收到的字符串 link
作为第一个参数传递(::1
是 localhost
的别名)。
s = getaddrinfo(link,"http", &hints,&result); ///////////////
更改代码导致:
woof@fth ~ % ./test.o google.com
google.com
sock_fd=3
socket opened
Successfully sent the fetch request
HTTP/1.0 404 Not Found
Content-Type: text/html; charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sun, 25 Jan 2015 11:07:09 GMT
Server: sffe
Content-Length: 1425
X-XSS-Protection: 1; mode=block
Alternate-Protocol: 80:quic,p=0.02
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}%
这意味着服务器响应。
找不到文件,因为在行
sprintf (link, "GET %s HTTP/1.0\r\n" "Host: %s\r\n\r\n", _path, _host);
您请求的路径不存在;如果你尝试
sprintf (link, "GET / HTTP/1.0\n\n");
您应该会看到一些不同的东西(可能是另一个错误)。如果您想获得不同的路径,您需要将其正确插入到请求中(努力从输入字符串中识别它)。
我编译的代码和你的差不多:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define LENGTH 500
int main(int argc, char** argv) {
// holds the value of the command-line argument
char link[LENGTH];
strcpy (link , argv[1]);
printf ("%s\n", link);
// break up link into the host and path -- use the "/"
char _host[LENGTH];
char _path[LENGTH];
int slashCount = 0;
int i,c;
for (i=0 ; i<strlen(link); i++) {
if (link[i] == '/')
slashCount ++;
if (slashCount > 2) {
// i is at the end of the host
strncpy (_host , link , i);
_host[i] = '[=15=]';
break;
}
}
if (slashCount == 2) {
// given only a host, copy the entire string into the host
strncpy(_host, link, i);
_host[i] = '[=15=]';
}
else {
// get the path for slashCount of 3
for (i ; strlen(link); i++ ) {
strcat (_path, &link[i]);
// if slash at the end of host name
if (strlen(_path) == 1)
{
// set the file field to be index.html
char t[11] = {'i','n','d','e','x','.','h','t','m','l','[=15=]'};
strncpy(_path, t, 11);
}
break;
}
} // end if/else
struct addrinfo hints;
struct addrinfo *result, *rp;
int sock_fd, s;
memset(&hints,0,sizeof(struct addrinfo)); // setting the values to 0
hints.ai_socktype = SOCK_STREAM; // tcp socket
// create addrinfo structure with parameters to initialize a socket
s = getaddrinfo("::1","8080", &hints,&result); ///////////////
if( s!=0 ) {
perror("error populating address structure");
exit(1);
}
char temp[5000];
// check the host name’s IP address — has a dynamic configuration(DNS)
// but does not change very frequently
for( rp=result; rp!=NULL; rp=rp->ai_next ) {
sock_fd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);
fprintf(stderr,"sock_fd=%d\n",sock_fd);
if (sock_fd == -1)
continue;
// exit loop on success
if( connect(sock_fd, rp->ai_addr, rp->ai_addrlen)==0 )
break;
else
close(sock_fd);
}
if( rp==NULL ) {
// you didn’t find a good ip address to connect with
fprintf(stderr, "could not connect\n");
exit(1);
}
else
printf("socket opened\n");
freeaddrinfo(result);
// formatting the request string
sprintf (link, "GET %s HTTP/1.0\r\n" "Host: %s\r\n\r\n", _path, _host);
// sending the request
if( send(sock_fd, link, strlen(link), 0)<0 )
fprintf(stderr, "Error with send\n");
else
fprintf (stderr, "Successfully sent the fetch request\n");
// response buffer
char buf[500];
memset(&buf,0,sizeof(buf));
int recv_count = recv(sock_fd, buf, 500, 0);
if( recv_count<0 ){
perror("Receive failed");
exit(1);
}
printf("%s",buf);
/* while (0 > recv (sock_fd, buf, 500, 0))
{
printf ("%s", buf);
}
shutdown(sock_fd,SHUT_RDWR); */
exit (0);
}
更改了函数调用并恢复了 sprintf
格式化 GET 请求。您应该在单独的终端上启动命令
echo "Here is a message" | nc -l -6 8080
它会暂停执行,直到您在端口上收到请求(标志 -l
,请参阅 netcat manual 了解更多信息)。
请求打印在 netcat 终端上,进程终止,而在您启动编译代码的终端上,您应该看到在 netcat 中回显和传输的消息。
我不确定 where/how 我的程序挂断了。我非常有信心发送或接收链接......但即使在互联网上搜索了一些帮助并得到了我教授的帮助之后,我仍然迷失了,为什么这不起作用。
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define LENGTH 500
int main(int argc, char** argv)
{
// holds the value of the command-line argument
char link[LENGTH];
strcpy (link , argv[1]);
printf ("%s\n", link);
// break up link into the host and path -- use the "/"
char _host[LENGTH];
char _path[LENGTH];
int slashCount = 0;
int i;
for (i=0 ; i<strlen(link); i++)
{
printf ("%c , slashcount: %d\n", link[i], slashCount);
if (link[i] == '/') slashCount ++;
if (slashCount > 2)
{
// i is at the end of the host
strncpy (_host , link , i);
_host[i] = '[=11=]';
break;
}
} // end for
if (slashCount == 2)
{
// given only a host, copy the entire string into the host
strncpy(_host, link, i);
_host[i] = '[=11=]';
}
else // get the path for slashCount of 3
{
for (i ; strlen(link); i++ )
{
strcat (_path, &link[i]);
// if slash at the end of host name
if (strlen(_path) == 1)
{
// set the file field to be index.html
char t[11] = {'i','n','d','e','x','.','h','t','m','l','[=11=]'};
for (int c=0; c< 10 ; c++)
strncpy(_path, t, 11);
}
break;
}
} // end if/else
printf ("%s\n" , _host); /*success*/
printf ("%s\n" , _path); /*success*/
struct addrinfo hints;
struct addrinfo * result, * rp;
int sock_fd, s;
hints.ai_socktype = SOCK_STREAM;
memset(&hints,0,sizeof(struct addrinfo)); // setting the values to 0
s = getaddrinfo("::1","http", &hints,&result); ///////////////
if (0 != s)
{
perror("error populating address structure");
exit(1);
}
printf ("entering tcp setup connections");
// check the host name’s IP address — has a dynamic configuration(DNS)
// but does not change very frequently
for (rp = result; rp != NULL; rp = rp->ai_next)
{
sock_fd = socket(rp->ai_family, rp->ai_socktype,
rp->ai_protocol);
if (sock_fd == -1)
continue;
if (connect(sock_fd, rp->ai_addr, rp->ai_addrlen) != -1)
break;
close(sock_fd);
}
if (rp == NULL)
{
// you didn’t find a good ip address to connect with
fprintf(stderr, "could not connect\n");
exit(1);
} // end for
freeaddrinfo(result);
// sending the request
sprintf (link, "GET %s HTTP/1.0\r\n" "Host: %s\r\n\r\n", _path, _host);
if (send (sock_fd, link, strlen(link), 0 )< 0)
fprintf (stderr, "Error with send\n");
else
fprintf (stderr, "Successfully send the fetch request\n");
// responding to the send
char buf[500];
memset(&buf,0,sizeof(buf));
/* int recv_count = recv(sock_fd, buf, 500, 0);
if(recv_count<0)
{
perror("Receive failed");
exit(1);
}
printf("%s",buf); */
/* while (0 > recv (sock_fd, buf, 500, 0))
{
printf ("%s", buf);
}
shutdown(sock_fd,SHUT_RDWR); */
exit (1);
}
明白了要发get请求,把response部分注释掉,看到有成功进入tcp连接设置。我只是对如何设置响应感到困惑。我知道如何使用 read/write,但我也想尝试 send/recv。
非常感谢任何帮助。
我目前得到的输出:
http://google.com/
h , slashcount: 0
t , slashcount: 0
t , slashcount: 0
p , slashcount: 0
: , slashcount: 0
/ , slashcount: 0
/ , slashcount: 1
g , slashcount: 2
o , slashcount: 2
o , slashcount: 2
g , slashcount: 2
l , slashcount: 2
e , slashcount: 2
. , slashcount: 2
c , slashcount: 2
o , slashcount: 2
m , slashcount: 2
/ , slashcount: 2
http://google.com
index.html
Successfully send the fetch request
entering tcp setup connections
recv()
的 return 值表示 Connection refused
,这表明套接字设置存在问题。
你需要把两行的顺序颠倒一下:
hints.ai_socktype = SOCK_STREAM;
memset(&hints,0,sizeof(struct addrinfo)); // setting the values to 0
以便您在 将内存设置为零后分配 ai_socktype
。
在 getaddrinfo()
调用中,从 cli 接收到的字符串 link
作为第一个参数传递(::1
是 localhost
的别名)。
s = getaddrinfo(link,"http", &hints,&result); ///////////////
更改代码导致:
woof@fth ~ % ./test.o google.com
google.com
sock_fd=3
socket opened
Successfully sent the fetch request
HTTP/1.0 404 Not Found
Content-Type: text/html; charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sun, 25 Jan 2015 11:07:09 GMT
Server: sffe
Content-Length: 1425
X-XSS-Protection: 1; mode=block
Alternate-Protocol: 80:quic,p=0.02
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}%
这意味着服务器响应。
找不到文件,因为在行
sprintf (link, "GET %s HTTP/1.0\r\n" "Host: %s\r\n\r\n", _path, _host);
您请求的路径不存在;如果你尝试
sprintf (link, "GET / HTTP/1.0\n\n");
您应该会看到一些不同的东西(可能是另一个错误)。如果您想获得不同的路径,您需要将其正确插入到请求中(努力从输入字符串中识别它)。
我编译的代码和你的差不多:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define LENGTH 500
int main(int argc, char** argv) {
// holds the value of the command-line argument
char link[LENGTH];
strcpy (link , argv[1]);
printf ("%s\n", link);
// break up link into the host and path -- use the "/"
char _host[LENGTH];
char _path[LENGTH];
int slashCount = 0;
int i,c;
for (i=0 ; i<strlen(link); i++) {
if (link[i] == '/')
slashCount ++;
if (slashCount > 2) {
// i is at the end of the host
strncpy (_host , link , i);
_host[i] = '[=15=]';
break;
}
}
if (slashCount == 2) {
// given only a host, copy the entire string into the host
strncpy(_host, link, i);
_host[i] = '[=15=]';
}
else {
// get the path for slashCount of 3
for (i ; strlen(link); i++ ) {
strcat (_path, &link[i]);
// if slash at the end of host name
if (strlen(_path) == 1)
{
// set the file field to be index.html
char t[11] = {'i','n','d','e','x','.','h','t','m','l','[=15=]'};
strncpy(_path, t, 11);
}
break;
}
} // end if/else
struct addrinfo hints;
struct addrinfo *result, *rp;
int sock_fd, s;
memset(&hints,0,sizeof(struct addrinfo)); // setting the values to 0
hints.ai_socktype = SOCK_STREAM; // tcp socket
// create addrinfo structure with parameters to initialize a socket
s = getaddrinfo("::1","8080", &hints,&result); ///////////////
if( s!=0 ) {
perror("error populating address structure");
exit(1);
}
char temp[5000];
// check the host name’s IP address — has a dynamic configuration(DNS)
// but does not change very frequently
for( rp=result; rp!=NULL; rp=rp->ai_next ) {
sock_fd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);
fprintf(stderr,"sock_fd=%d\n",sock_fd);
if (sock_fd == -1)
continue;
// exit loop on success
if( connect(sock_fd, rp->ai_addr, rp->ai_addrlen)==0 )
break;
else
close(sock_fd);
}
if( rp==NULL ) {
// you didn’t find a good ip address to connect with
fprintf(stderr, "could not connect\n");
exit(1);
}
else
printf("socket opened\n");
freeaddrinfo(result);
// formatting the request string
sprintf (link, "GET %s HTTP/1.0\r\n" "Host: %s\r\n\r\n", _path, _host);
// sending the request
if( send(sock_fd, link, strlen(link), 0)<0 )
fprintf(stderr, "Error with send\n");
else
fprintf (stderr, "Successfully sent the fetch request\n");
// response buffer
char buf[500];
memset(&buf,0,sizeof(buf));
int recv_count = recv(sock_fd, buf, 500, 0);
if( recv_count<0 ){
perror("Receive failed");
exit(1);
}
printf("%s",buf);
/* while (0 > recv (sock_fd, buf, 500, 0))
{
printf ("%s", buf);
}
shutdown(sock_fd,SHUT_RDWR); */
exit (0);
}
更改了函数调用并恢复了 sprintf
格式化 GET 请求。您应该在单独的终端上启动命令
echo "Here is a message" | nc -l -6 8080
它会暂停执行,直到您在端口上收到请求(标志 -l
,请参阅 netcat manual 了解更多信息)。
请求打印在 netcat 终端上,进程终止,而在您启动编译代码的终端上,您应该看到在 netcat 中回显和传输的消息。