提醒:
最近沒有發表什麼文章,但偶然發現部落格排名一直向前走,才讓我又回到了部落格的空間來。
1.最近有些網友在關注我寫的C++的筆記,我想說的是:那是前段時間自己複習基礎文法,順便寫下來的,沒有多大的參考價值,希望需要的網友參考比較完整的書籍,不希望網友浪費寶貴的時間。
2.在一月份曾經發布了C語言版本(Linux平台)的CSDN部落格備份工具,有很多感興趣的,初學Linux的網友將代碼作為參考,有個需要注意的:代碼的效率有改進的空間,而且使用方法和注釋可能會誤導初學者,所以建議需要的網友查詢相關資料以保證代碼使用的正確方法。
有一個需要提的,在代碼裡面,用到了select函數,在這裡我簡單的提一下:
static int recv_response(const blog_spider * spider){int ret, end, recvsize, count;char recvbuf[BUFSIZE];fd_set read_fds;struct timeval timeout;FILE *fp;/*建議時間要長點, select失敗可能的原因是收到網站的響應訊息逾時,也可以傳入NULL*/timeout.tv_sec = 30;timeout.tv_usec = 0;FD_ZERO(&read_fds);FD_SET(spider->blog->b_sockfd, &read_fds);while (1) {ret = select(spider->blog->b_sockfd+1, &read_fds, NULL, NULL, &timeout);if (-1 == ret) {/*出錯,直接返回錯誤*/#ifdef SPIDER_DEBUGfprintf(stderr, "select: %s\n", strerror(errno));#endifreturn -1;}else if (0 == ret) {/*逾時, 繼續輪詢*/#ifdef SPIDER_DEBUGfprintf(stderr, "select timeout: %s\n", spider->blog->b_title);#endifgoto fail_recv_response;}/*接受到資料*/if (FD_ISSET(spider->blog->b_sockfd, &read_fds)) {end = 0;count = 0;/*這裡出錯可能是檔案名稱不規則,比如"3/5",'/'在Linux是代表目錄*/fp = fopen(spider->blog->b_local_file, "w+");if (NULL == fp) {goto fail_recv_response;}spider->blog->b_download = BLOG_DOWNLOAD;while (read(spider->blog->b_sockfd, recvbuf, 1) == 1) {if(end< 4) {if(recvbuf[0] == '\r' || recvbuf[0] == '\n') {end++;}else {end = 0;}/*這裡是http伺服器反饋的訊息頭,若需要,則可以儲存下來*/}else {fputc(recvbuf[0], fp);count++;if (1024 == count) {fflush(fp);}}}fclose(fp);break;}}FD_CLR(spider->blog->b_sockfd, &read_fds);return 0;fail_recv_response:spider->blog->b_download = BLOG_UNDOWNLOAD;FD_CLR(spider->blog->b_sockfd, &read_fds);return -1;}
在使用select(spider->blog->b_sockfd+1, &read_fds, NULL, NULL, &timeout)函數時,由於select會把timeout結構體給清空,所以若要使用自訂逾時時間,必須在select函數返回之後,重新設定timeout結構體。
或者直接傳NULL,無限等待,這樣也可以,希望不要誤導初學者。
3.在查詢部落格鏈表長度,我每次重新遍曆,可以再改進,原來的代碼:
/*********************************************************返回爬蟲鏈表長度*********************************************************/static int spider_size(blog_spider * spider_head){int count = 0;blog_spider *pspider;pspider = spider_head;while (pspider->next) {pspider = pspider->next;count++;}return count;}
每次重新遍曆鏈表,效率很低,可以設定一個全域變數來儲存長度。也可以設定一個指向最後一個節點的指標,每次求長度只需與首節點地址想減,再除以指標大小,就可以得到長度。