2012-08-14 67 views
2

我有一些代碼使用BSD套接字從服務器抓取網頁並將其寫入文件。以下是處理所有文件I/O以及使用套接字進行寫入和讀取的代碼。需要注意的是_sockfd是說話者和聽者之間的有效插座:不尋常的意外值插入到HTML頁面抓取

FILE* resultFile; 
    resultFile = fopen(resultFilename.c_str(), "w+"); 

    if (resultFile != 0) 
    { 
     // Construct the request 
     std::stringstream requestBuilder(""); 
     requestBuilder << "GET " << directory << " HTTP/1.1\r\nHOST:" << _hostname << "\r\n\r\n"; 

     std::string request = requestBuilder.str(); 

     // Prepare to read the file and write it out 
     int bufferSize(1024); 
     char buffer[bufferSize]; 
     int bytesRead(1); 

     // Send request 
     int bytesWritten = write(_sockfd, request.c_str(), request.length()); 
     if (bytesWritten < 0) 
     { 
      std::cout << "Error on initial request send" << std::endl; 
      return false; 
     } 

     // Read response 
     while (bytesRead > 0) 
     { 
      bzero(buffer, bufferSize); 
      bytesRead = read(_sockfd, buffer, bufferSize); 

      if (bytesRead < 0) 
      { 
       std::cout << "WebCrawler -> ERROR: Could not read properly from socket" << std::endl; 
       return false; 
      } 

      fputs(buffer, resultFile); 
     } 

     fclose(resultFile); 
     _socketUsed = true; 

,我希望這個代碼產生的結果看起來像下面的代碼片段:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 

<head> 
<title>Serebii.net Pok&eacute;dex - #089 Muk</title> 

<meta name="GENERATOR" content="Arachnophilia 4.0"> 
<meta name="FORMATTER" content="Arachnophilia 4.0"> 
<meta name="keywords" content="Pokemon, Pokédex, Muk (Pokémon),Muk, Diamond, Pearl, Platinum,  HeartGold, SoulSilver" /> 
<link rel="stylesheet" type="text/css" HREF="/style/dex.css"> 

</head> 

<meta http-equiv="imagetoolbar" CONTENT="no"> 
    <link rel="stylesheet" type="text/css" HREF="http://www.serebii.net/spp-temp.css"> 
    <LINK REL="SHORTCUT ICON" HREF="http://www.serebii.net/favicon.ico"> 

<BODY ondragstart="return false" text=#000000 bottomMargin=0 bgcolor="#383838" 
leftMargin=0 topMargin=0 rightMargin=0> 
    <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse"  bordercolor="#111111" width="100%" height="1" background="http://www.serebii.net/BannerBg.jpg"> 
     <tr> 

但是,相反,它看起來是這樣的:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html> 

<head> 
<title>Serebii.net Pok&eacute;dex - #089 Muk</title> 

<meta name="GENERATOR" content="Arachnophilia 4.0"> 
<meta name="FORMATTER" content="Arachnophilia 4.0"> 
<meta name="keywords" content="Pokemon, PokÈdex, Muk (PokÈmon),Muk, Diamond, Pearl, Platinum,  HeartGold, SoulSilver" /> 
<link rel="stylesheet" type="text/css" HREF="/style/dex.css"> 

</head> 


8c1 
<meta http-equiv="imagetoolbar" CONTENT="no"> 
    <link rel="stylesheet" type="text/css" HREF="http://www.serebii.net/spp-temp.css"> 
    <LINK REL="SHORTCUT ICON" HREF="http://www.serebii.net/favicon.ico"> 

<BODY ondragstart="return false" text=#000000 bottomMargin=0 bgcolor="#383838" 
leftMargin=0 topMargin=0 rightMargin=0> 
    <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%" height="1" background="http://www.serebii.net/BannerBg.jpg"> 
     <tr> 

正如你看到的,我的代碼以某種方式插入奇怪的字符(在這種情況下,「8C1」)到的結果。我想強調的是,這在整個HTML文檔中都會發生多次。爲簡潔起見,我僅僅將自己侷限於一個例子。我懷疑我可能會以某種方式濫用緩衝區,但到目前爲止我一直無法找到解決方案。

包括在我以前的努力,以解決我的問題在以下做題:

C Winsock programming: input garbage

Raw Sockets : Receiver printing garbage values

我還引用了以下頁面,以確保我在做C文件I/O正確(我習慣用C與fstream的工作++):

http://www.cprogramming.com/tutorial/cfileio.html

我對使用套接字的網絡編程非常缺乏經驗(正如你可能知道的那樣),並且我確信這是一個愚蠢的錯誤。對於那些比我更有經驗的人:即使你不能直接指出我的解決方案,請分享你對我可能犯錯的地方的看法。有時候,我們需要找到答案的只是一些放置良好的麪包屑。爲此,請告訴我是否顯示錯誤的代碼和/或您認爲代碼的另一部分可能更有用。

此外,這是我的第一個SO問題。請按照您認爲合適的方式對其進行評論,以確保我的未來問題更好,更適合網站。

****更新1 ****(馬克贖金的建議後更改的fputs到使用fwrite):

我改變fputs(buffer, resultFile);fwrite(buffer, 1, bytesRead, resultFile);。我現在看到,在這種情況下使用更合適。

但是,我的問題依然存在。事實上,我發現在新代碼(和我的舊代碼)連續執行5次後,我在原始問題中錯誤地稱爲「垃圾」值的錯誤值每次都完全相同。他們根本不是隨機的。我改變了我的問題的標題,以更恰當地描述我的問題。

經過一番更多的討論後,我想補充說,在讀取產生與文件寫入相同的結果後,將buffer打印到控制檯。

+0

您已將此標籤標記爲「C」,但是......「std :: string」。不是C,這是C++(不管你使用C風格的IO)。 – 2012-08-14 21:50:35

+1

這裏的問題沒有問題。你給出了代表你的問題的很好的一小段代碼,以及「我期待這一點,但我得到了這個」的輸出。真的不能要求更好。歡迎來到這個網站。 – 2012-08-14 21:59:07

+0

@Jared Friese嘗試附加一個調試器,如gdb或VS.您可能想在每次讀取後查看'bytesRead'的值。看起來你有套接字編程,只是現在寫的二進制文件。祝你好運。 – MartyE 2012-08-14 23:10:02

回答

3

您在fputs(buffer, resultFile);中得到緩衝區溢出,因爲寫入並未停在緩衝區的末尾 - 它停止在找到的第一個零字符處,該字符位於內存中的某個隨機點之後緩衝。改爲使用fwrite

+0

打敗我吧。自從我認爲這是問題之後,我不得不查找fputs。 – 2012-08-14 21:57:28

+0

@凱文,沒有必要去查找它。該函數沒有任何可以定義要寫入的字節數的參數,所以問題很明顯。 – 2012-08-14 22:03:52

+0

@凱文同意/ upvote。值得一提的是在'fwrite'命令中明確檢查'bytesRead'。 – MartyE 2012-08-14 22:22:16