2015-08-08 141 views
0

我完全不熟悉网络编程。所以,我的工作是通过这样的插座上的一个程序,并尝试读取HTML内容(我认为这是在HTML,有人纠正我在这个):C recv()不在缓冲区中读取

GET infolab.stanford.edu/~ullman/focs.html HTTP/1.1\r\n 
Host: www.google.com\r\n 
\r\n 

infolab.stanford.edu/~ullman/focs.html是网站我正在阅读。

因此,我将那条GET消息存储在一个字符串中,然后使用send()方法将请求发送到服务器。我检查了errno,它返回Success

然后,我使用recv()来读取内容并将其存储在缓冲区中。我做了一些搜索,发现缓冲[6000]就像一个标准。

但是,我的程序需要永远运行recv()。 errno返回Success,但是当我尝试打印缓冲区时,它只是一个空行。

int open_clientfd(char *hostname, int port) 
{ 
    int clientfd; 
    struct hostent *hp; 
    struct sockaddr_in serveraddr; 

    if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     return -1; /* Check errno for cause of error */ 

    /* Fill in the server's IP address and port */ 
    if ((hp = gethostbyname(hostname)) == NULL) 
     return -2; /* Check h_errno for cause of error */ 
    bzero((char *) &serveraddr, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 
    bcopy((char *)hp->h_addr_list[0], 
     (char 
      *)&serveraddr.sin_addr.s_addr, 
     hp->h_length); 
    serveraddr.sin_port = htons(port); 

    /* Establish a connection with 
    * the server */ 
    if (connect(clientfd, (SA *) 
      &serveraddr, 
      sizeof(serveraddr)) < 0) 
     return -1; 
    return clientfd; 
} 

void sendRequest(int clientfd, char request[128]) { 
    char buffer[6000]; 
    int byteSent, byteRead; 

    // send request 
    byteSent = send(clientfd, request, sizeof(request), 0); 
    fprintf(stderr, "%s\n", strerror(errno)); 

    // read 
    byteRead = recv(clientfd, buffer, sizeof(buffer), 0); 
    fprintf(stderr, "%s\n", strerror(errno)); 

    fprintf(stdout, "%s\n", buffer); 
} 

int main(int argc, char **argv) { 
    int clientfd, port; 
    char *host, *fileURL; 

    rio_t rio; 

    host = argv[1]; 
    fileURL = argv[2]; 

    port = atoi(argv[3]); 

    clientfd = open_clientfd(host, port); 

    // set up request string 
    char request[128]; 

    // .... 

    // now request stores the string above 

    sendRequest(clientfd, request); 

    return 0; 
} 
+1

通常嫌疑犯:治疗缓冲区作为空终止字符数组时,不能保证如此。未能正确处理recv()返回的结果。 –

+0

对于其中一个,'sendRequest'中的'send'调用中的'sizeof(request)'并不是按照您的想法进行的。当请求变量作为参数传递时,request变量是一个通过转换的指针,而不是来自调用者的数组,因此sizeof会正确地给出你所要求的:指针的大小。还有次要的,但它仍然不应该发生,没有'Open_clientfd',但有'open_clientfd'。 – WhozCraig

+1

..如果您正在考虑针对@WhozCraig评论达成strlen(),请再考虑一次。将希望发送的字节数作为单独的参数传递。 –

回答

3

您的设置对于您的请求是错误的。首先,您发送的数据相当于指针的大小,而不是请求缓冲区。其次,GET请求不应包含站点名称;用于建立连接。

下面介绍了一个精简版的设置和调用工程。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <netdb.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netinet/ip.h> 

int open_clientfd(char *hostname, int port) 
{ 
    int clientfd; 
    struct hostent *hp; 
    struct sockaddr_in serveraddr; 

    if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
     return -1; /* Check errno for cause of error */ 

    /* Fill in the server's IP address and port */ 
    if ((hp = gethostbyname(hostname)) == NULL) 
     return -2; /* Check h_errno for cause of error */ 
    bzero((char *) &serveraddr, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 
    bcopy((char *)hp->h_addr_list[0], 
      (char *)&serveraddr.sin_addr.s_addr, 
      hp->h_length); 
    serveraddr.sin_port = htons(port); 

    /* Establish a connection with the server */ 
    if (connect(clientfd, (const struct sockaddr*) 
       &serveraddr, 
       sizeof(serveraddr)) < 0) 
     return -1; 
    return clientfd; 
} 

void sendRequest(int clientfd, char request[], size_t rlen) 
{ 
    ssize_t byteSent, byteRead; 

    // send request 
    byteSent = send(clientfd, request, rlen, 0); 
    if (byteSent < 0) 
    { 
     fprintf(stderr, "%s\n", strerror(errno)); 
     return; 
    } 

    // read response 
    do 
    { 
     char buffer[1024]; 
     byteRead = recv(clientfd, buffer, sizeof(buffer)-1, 0); 
     if (byteRead < 0) 
     { 
      fprintf(stderr, "%s\n", strerror(errno)); 
      return; 
     } 

     buffer[byteRead] = 0; 
     fprintf(stdout, "%s", buffer); 

    } while (byteRead > 0); 
} 

int main(int argc, char **argv) 
{ 
    int clientfd = open_clientfd("infolab.stanford.edu", 80); 
    if (clientfd < 0) 
    { 
     perror(NULL); 
     return EXIT_FAILURE; 
    } 

    // set up request string 
    char request[] = "GET /~ullman/focs.html HTTP/1.1\r\n" 
        "Host: www.google.com\r\n" 
        "\r\n"; 

    // now request stores the string above 
    sendRequest(clientfd, request, sizeof(request)-1); 
    close(clientfd); 

    return 0; 
} 

输出

HTTP/1.1 200 OK 
Date: Sat, 08 Aug 2015 16:24:56 GMT 
Server: Apache/2.2.3 (CentOS) 
Last-Modified: Wed, 17 Mar 2010 21:53:56 GMT 
ETag: "3448c4fe-f93-269bc500" 
Accept-Ranges: bytes 
Content-Length: 3987 
Content-Type: text/html; charset=UTF-8 

<TITLE>Aho/Ullman Foundations of Computer Science</TITLE> 

<BODY BGCOLOR = "E0F7F0"> 

<CENTER><TABLE> 
<TR><TD><IMG SRC = "gifs/focs.gif"></td> 
<TD ALIGN = MIDDLE><FONT SIZE = 6>Foundations of Computer 
Science</font></td></tr> 
<TR></tr> 
</TABLE></CENTER> 
<P> 
This book has been taken out of print by W. H. Freeman. 
You are welcome to use it if you like. 
We believed in 1992 it was the way to introduce theory in 
Computer Science, and we believe that today. 
<P> 
<CENTER>--- Al Aho and Jeff Ullman</center> 
<P> 
<H3>Index</H3> 
<P> 
<A href="#pdfs">The Book</a> | 
<A href="#supp">Materials</a> | 
<A href="#grad">Gradiance</a> | 
<A href="#errata">Errata</a> 

<A name="pdfs"></a> 
<H3>PDF's of the Book</H3> 
<P> 
<UL> 
<LI><A href="focs/preface.pdf">Preface</a> 
<LI><A href="focs/toc.pdf">Table of Contents</a> 
<LI><A href="focs/ch01.pdf">Chapter 1</a> Computer Science: The 
Mechanization of Abstraction 
<LI><A href="focs/ch02.pdf">Chapter 2</a> Iteration, Induction, and 
Recursion 
<LI><A href="focs/ch03.pdf">Chapter 3</a> The Running Time of Programs 
<LI><A href="focs/ch04.pdf">Chapter 4</a> Combinatorics and Probability 
<LI><A href="focs/ch05.pdf">Chapter 5</a> The Tree Data Model 
<LI><A href="focs/ch06.pdf">Chapter 6</a> The List Data Model 
<LI><A href="focs/ch07.pdf">Chapter 7</a> The Set Data Model 
<LI><A href="focs/ch08.pdf">Chapter 8</a> The Relational Data Model 
<LI><A href="focs/ch09.pdf">Chapter 9</a> The Graph Data Model 
<LI><A href="focs/ch10.pdf">Chapter 10</a> Patterns, Automata, and 
Regular Expressions 
<LI><A href="focs/ch11.pdf">Chapter 11</a> Recursive Description of 
Patterns 
<LI><A href="focs/ch12.pdf">Chapter 12</a> Propositional Logic 
<LI><A href="focs/ch13.pdf">Chapter 13</a> Using Logic to Design 
Computer Components 
<LI><A href="focs/ch14.pdf">Chapter 14</a> Predicate Logic 
<LI><A href="focs/index.pdf">Index</a> 
</ul> 

<A name="supp"></a> 
<H3>Supplementary Materials</H3> 
<P> 
<UL> 
<LI><A HREF = "pub/sols-fcsc-new.ps">Solutions to Selected Exercises</a> 
<LI><A HREF = "fcs-exams.html">A Selection of Exams and Projects</A> 
<LI><A HREF = "fcsc-notes.html">Jeff Ullman's Lecture Notes</A> 
(ancient) 
<LI><A HREF = "fcsc-figures.html">The Programs Appearing in the Book</a> 
</ul> 

<A name="grad"></a> 
<H3>Gradiance Package Available</H3> 

<P> 
<A href="http://www.gradiance.com">Gradiance</a> 
is offering a free trial of its automated homeworks for the topics 
covered by this book. These homeworks are designed as a teaching aid 
rather than an assessment tool. Students get advice when they make a 
mistake and are encouraged to try working on the same problem(s) until 
they get them right. If you would like to try the system gratis for 
your class, make yourself an account at <A 
href="http://www.gradiance.com/services"><TT>www.gradiance.com/services</tt></a>. 
Then, send email to sup port @grad iance .com (ignore the blanks in that 
email address, of course) telling us your login and that you would like 
to try the discrete-math product. You can find manuals for 
instructors, students, and question-authors at <A 
href="http://www.gradiance.com/info.html"><TT>www.gradiance.com/info.html</tt></a>. 
<P> 
<B>Special offer for students</b>: Until June 30, 2009, we have made use of the 
Gradiance materials available for students whose instructors are not using 
the system. Make yourself an account on 
<A href="http://www.gradiance.com/services"><TT>www.gradiance.com/services</tt></a>, 
and then sign up for the class 8CD5ED01. You will be able to work 31 selected 
homeworks, and will get advice when you make an error. The only difference is that 
we cannot reveal solutions, because these assignments are open indefinitely. 

<A name="errata"></a> 
<H3>Errata Sheet</H3> 

We are going to try to maintain errata. Please see 
<A href="focs/errata.html">The Errata Sheet</a>. 
If you find an unreported error, please send email to ullman 
at gmail dot com. 

<!-- --> 
<script src="http://tags.stanford.edu/tags.js" type="text/javascript"></script> 
<!-- --> 

</BODY> 
+0

谢谢! 你能解释为什么它必须是sizeof(request) - 1吗? – PTN

+0

@ main()中@PTN'sizeof(request)'包含终止的nullchar,我们*不希望发送。 – WhozCraig