2011-03-22 95 views
0

問候所有。爲多個HTTP連接重新使用客戶端TCP套接字

我在Linux 2.6.29-3.ydl61.3上製作了一個ANSI C多線程www爬蟲(HTTP 1.1兼容),並且進展順利。我在MySQL數據庫中有'000個域來收集頁面。根據需要,我可以在保持活動模式下打開搜尋器中的任何/所有域。我使用POSIX線程,並且沒有任何爭用或數據競賽。

儘管目標服務器似乎準備好允許我爲每個服務器套接字上的頁面發出多個併發或順序請求(因爲每個服務器都如預期的那樣返回'Connection:Keep-Alive'),所以我實際上無法這樣做...我只能每個套接字連接獲取一個頁面......即,我可以通過文件描述符向套接字寫入典型的HTTP GET請求,並讀取響應。然後在那之後,我只能寫信給fd但不能讀取!因此,雖然每個域有多個(一些到幾百個)urls ...似乎我必須不斷重新創建與每個寫入/讀取相同服務器的套接字連接(極度浪費內存而且速度慢),而不是僅創建一個客戶端TCP連接並繼續重複使用fd/socket直到完成域。

參見下面的「netstat的--inet -a」的部分輸出(注意,由於不希望的我有多個本地套接字連接到相同域 - 這些不是每個域併發):

TCP 0 0 gcell1 :38614 x2web02.myhosting.com:http CLOSE_WAIT TCP 0 0 gcell1:34678 x2web02.myhosting.com:http CLOSE_WAIT TCP 0 0 gcell11:34768 x2web02.myhosting.com:http CLOSE_WAIT TCP 0 0 gcell11:56085個www.hihostels .com:http CLOSE_WAIT tcp 0 0 gcell11:34661 x2web02.myhosting.com:http CLOSE_WAIT tcp 0 0 gcell11:34785 x2web02.myhosting.com:http CLOSE_WAIT tcp 0 0 gcell11:46660 67.225.194.54:http CLOSE_WAIT tcp 0 0 gcell11:34697 x2web02.myhosting.com:http CLOSE_WAIT tcp 0 0 gcell11:37510 www.kenic.or.ke:http CLOSE_WAIT tcp 0 0 gcell11:37516 www.kenic.or.ke:http CLOSE_WAIT TCP 0 0 gcell11:34710 x2web02.myhosting.com:http CLOSE_WAIT TCP 0 0 gcell11:34711 x2web02.myhosting.com:http CLOSE_WAIT TCP 0 0 gcell11:46677 67.225.194.54 :HTTP CLOSE_WAIT TCP 0 0 gcell11:56513 www.kenic.or.ke:http CLOSE_WAIT TCP 0 0 gcell11:57560 x2web02.myhosting.com:http CLOSE_WAIT TCP 0 0 gcell11:46634 67.225.194.54:http CLOSE_WAIT TCP 0 0 gcell11:46607 67.225.194.54:http CLOSE_WAIT TCP 0 0 gcell11:46666 67.225.194.54:http CLOSE_WAIT TCP 0 0 gcell11:37526 www.kenic.or.ke:http CLOSE_WAIT TCP 0 0 gcell11:46673 67.225.194.54:http CLOSE_WAIT TCP 0 0 gcell11:34736 x2web02.myhosting.com:http CLOSE_WAIT TCP 0 0 gcell11:57557 x2web02.myhosting.com:http CLOSE_WAIT TCP 0 0 gcell11:56395 www.kenic.or.ke:http CLOSE_WAIT TCP 0 0 gcell11:34714 x2web02.myhosting .com:http CLOSE_WAIT tcp 0 0 gcell11:34669 x2web02.myhosting.com:http CLOSE_WAIT tcp 0 0 gcell11:34767 x2web02.myhosting.com:http CLOSE_WAIT tcp 0 0 gcell11:43381 ip-72-167-251- 99.ip.se:http CLOSE_WAIT

客戶端套接字如下(僅部分碼)

if((http_socket_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP))!=SKMG_FAILURE) //typical 
... 
fcntl(http_socket_fd,SOCK_NONBLOCK); //set to non-block 
... 
setsockopt(http_socket_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); //local TCP keep-alive used 
... 
while(connect(http_socket_fd, (struct sockaddr *)&http_name, sizeof (struct sockaddr_in)) == (-1)) 
... 
return http_socket_fd; 

此我只是用寫入/在FD讀出後建立。而且它的功能完美,但只有一次往返旅行。

1)我怎樣才能重複使用http_socket_fd每個HTTP GET寫/讀每個域,而不需要爲每個url創建一個新的本地TCP套接字?僅僅將http_socket_fd傳遞給每個域的每個頁面獲取調用正是失敗的工作。 [關鍵]

2)我怎樣才能在這個服務器上的每個域的範例每個套接字的這一個線程的異步請求?我運行4個併發線程(我的服務器是雙線程的),即4個不同的併發域提取。 [NON-CRITICAL]

+0

你可以添加一個示例請求/響應? – Hasturkun 2011-03-22 11:16:13

+0

有人請幫助!爲什麼我不能重複使用http客戶端套接字,因爲我沒有調用close(http_socket_fd)?我不想繼續爲相繼的請求重新創建一個新的客戶端連接套接字。 C中不可能重複使用開放客戶端套接字(已啓用HTTP保持連接)進行連續讀取/寫入?使用Java http://www.mail-archive.com/[email protected]/msg04687.html – EdNdee 2011-04-23 14:20:06

回答

0

通常的做法是爲每個連接創建一個客戶端套接字。在線程之間共享套接字也是一個壞主意。

而不是編寫自己的HTTP客戶端,你有沒有考慮過使用像libcurl這樣的庫,它提供了許多高級功能? libcurl網站有a sample program使用多線程下載內容。還有看看ZeroMQ,一個高性能的消息框架。 ZeroMQ套接字可用於連接到多個服務器並有效地下載數據。 (見The Guide)。

+0

Vijay似乎有可能,感謝您使用第三方庫的快速響應和建議。更正,我不會共享線程套接字!我清楚地這麼說...「每個域的範例每個套接字一個線程」...我池中的4個線程的每個線程只處理一個套接字,而每個套接字又只連接到一個域。我的問題與保持每個域的所有後續連接的確切方法有關。關於3rdp圖書館,這是我不願意處理黑盒子的罕見場合之一,並且出於特定原因需要絕對控制代碼。 – EdNdee 2011-03-22 06:46:33