2016-03-03 154 views
0

我試圖代理HTTP請求到另一臺HTTP服務器。上游HTTP服務器的主機名和端口號分別爲server_proxy_hostname和server_proxy_port。在C:代理HTTP請求到另一臺服務器

第一步將執行server_proxy_hostname的DNS查找。

其次,我創建一個網絡套接字並將其連接到我從DNS獲得的IP地址。

最後一步:等待兩個插座上的新數據。當數據到達時,我立即將其讀取到緩衝區,然後將其寫入另一個 套接字。這保持HTTP客戶端和上游HTTP服務器之間的雙向通信。

如果任何插座關閉,我關閉另一個。


現在的問題是它不工作。 (它超時)

我相信我得到我的IP地址的方式是正確的,所以問題必須在我的while循環(它永遠不會終止?)或我稱爲connect()的部分? 。我試着爲read()和select()添加錯誤終止,但那也不起作用。

void handle_proxy_request(int fd) { 

    char * targetHostName = server_proxy_hostname; 
    int targetPort = server_proxy_port; 
    struct hostent *info; 
    info = gethostbyname(targetHostName); 
    struct in_addr ** ipAddresslist; 
    ipAddresslist = (struct in_addr **) (info -> h_addr_list); 
    struct in_addr * ipAddress = ipAddresslist[0]; 
    printf("ip address is %s\n", inet_ntoa(*ipAddress)); 

    /*ip for in_addr struct*/ 
    unsigned long ip = inet_addr(inet_ntoa(*ipAddress)); 
    struct in_addr addressIp = {ip}; 
    struct sockaddr_in address = {PF_INET, htons(targetPort), addressIp}; 

    int socket_num = socket(PF_INET, SOCK_STREAM, 0); 
    connect(socket_num, (struct sockaddr *)&address, sizeof(address)); 

    /*portion for select()*/ 
    char buf[10000]; 
    int nfds = (fd > socket_num)?fd:socket_num; 
    fd_set readSet; 
    fd_set writeSet; 

    while (1) { 

    FD_ZERO(&readSet); 
    FD_ZERO(&writeSet); 
    FD_SET(fd, &readSet); 
    FD_SET(socket_num, &readSet); 
    FD_SET(fd, &writeSet); 
    FD_SET(socket_num, &writeSet); 
    int selectReturn = select(nfds, &readSet, &writeSet, NULL, NULL); 
    if (selectReturn == -1){ 
     break; 
    } 
    if(FD_ISSET(fd, &readSet)){ 
     int readStat = read(fd, buf, sizeof(buf)); 
     int status = write(socket_num, buf, sizeof(buf)); 
     if (status == -1 || readStat == -1){ 
     close(socket_num); 
     close(fd); 
     break; 
     } 
     /*memset(buf, 0, sizeof(buf));*/ 
    } 
    if(FD_ISSET(socket_num, &readSet)){ 
     int readStat2 = read(socket_num, buf, sizeof(buf)); 
     int status2 = write(fd, buf, sizeof(buf)); 
     if (status2 == -1 || readStat2 == -1){ 
     close(socket_num); 
     close(fd); 
     break; 
     } 
    } 

    } 

} 
+0

如果你不知道具體哪個部分被掛起,我會建議添加更多的調試日誌(或上面的代碼樣式中的'printf'),並嘗試用調試器進行調試。爲什麼你認爲IP地址代碼是正確的?你確定'connect'實際上有連接嗎?你有沒有嘗試telnet到地址和端口,以確保它響應連接? –

回答

1
int socket_num = socket(PF_INET, SOCK_STREAM, 0); 

未選中。檢查這個錯誤。

connect(socket_num, (struct sockaddr *)&address, sizeof(address)); 

同上。

FD_SET(fd, &writeSet); 
FD_SET(socket_num, &writeSet); 

刪除。這是不好的做法。套接字是幾乎總是準備好寫的,所以你不應該使用writeSet,除非你以前遇到過的情況下一個套接字還沒有準備好寫,即write()errno == EAGAIN/EWOULDBLOCK.

int readStat = read(fd, buf, sizeof(buf)); 
int status = write(socket_num, buf, sizeof(buf)); 

應該返回-1

int status = write(socket_num, buf, readStat); 

在這兩種情況下,插座。

並且它應該是之前通過試驗readStat == 0,表示流的末尾,和readStat == -1,指示錯誤,你應該跟蹤。

在此代碼不能得到超時,因爲你沒有設置任何。

有皺紋。如果讀取一個套接字的流結束,則應關閉另一個套接字進行輸出。如果您已經關閉了輸出的套接字上的流結束,請關閉它們兩者。這會在正確的時間在兩個方向上正確傳播FIN。

當您從任何系統呼叫時,您必須立即電話perror()與結果strerror()記錄它調用任何其他系統調用之前得到任何錯誤。

+0

「這裏有一個問題,如果你在讀取一個套接字的流結束,你應該關閉另一個套接字輸出,如果你的套接字已經關閉了,輸出結束,關閉它們。兩個方向在正確的時間。「你能詳細解釋一下嗎?我現在確實正在通過對等方重置[Errno 104]連接。 –

+0

另外,你是什麼意思「關閉」一個「輸出套接字」?你的意思是「接近」嗎? –

+0

謝謝。你說的一切都有幫助,而且是真的。當我改變第一個輸入select(),nfds到FD_SETSIZE時,它現在可以工作。 –

相關問題