2015-08-08 152 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