2013-04-03 125 views
1

我試圖製作一個在winsock中使用HTTP的程序,但我遇到了recv函數只是掛在那裏的問題。在C++中的Winsock中發送HTTP GET請求後,Recv()函數掛起

int connect() 
{ 
WSADATA t_wsa; //WSADATA structure 
WORD wVers = 0x0202; //version number 
int iError; //error number 

wVers = MAKEWORD(2, 2); // Set the version number to 2.2 
iError = WSAStartup(wVers, &t_wsa); // Start the WSADATA 

if(iError != NO_ERROR || iError == 1) 
{ 
    printf("Error at WSAStartup()\n"); 
    WSACleanup(); 
    system("PAUSE"); 
    return 1; 
} 

/* Correct version? */ 
if(LOBYTE(t_wsa.wVersion) != 2 || HIBYTE(t_wsa.wVersion) != 2) 
{ 
    printf("Incorrect version\n"); 
    WSACleanup(); 
    system("PAUSE"); 
    return 1; 
} 

SOCKET sClient; 
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
if(sClient == INVALID_SOCKET || iError == 1) 
{ 
    printf("Invalid Socket!\n"); 
    WSACleanup(); 
    system("PAUSE"); 
    return 1; 
} 
SOCKADDR_IN sinClient; 
memset(&sinClient, 0, sizeof(sinClient)); 

char cIP[50]; 
strcpy_s(cIP, "98.139.183.24"); 
sinClient.sin_family = AF_INET; 
sinClient.sin_addr.s_addr = inet_addr(cIP); // Where to start server 
sinClient.sin_port = htons(80); //Port 

if(connect(sClient, (LPSOCKADDR)&sinClient, sizeof(sinClient)) == SOCKET_ERROR) 
{ 
    /* failed at starting server */ 
    printf("Could not connect ot the server!\n"); 
    WSACleanup(); 
    system("PAUSE"); 
    return 1; 
} 

// Now we can send/recv data! 
printf("YOU ARE CONNECTED!\r\n"); 
string buffer; 
buffer += "GET/HTTP/1.1\r\n"; 
buffer += "Host: http://www.yahoo.com/\r\n"; 
buffer += "Connection: close\r\n\r\n"; 
const char *cha = buffer.c_str(); 


int sent; 
int response; 
sent = send(sClient, cha, sizeof(cha) - 1, 0); 

char recvbuf[50000]; 

response = recv(sClient, recvbuf, 50000, 0); 
recvbuf[response] = '\0'; 
printf("\nReceived data = %s", recvbuf); 
WSACleanup(); 
return(0); 
} 

「sent」將在send函數後打印,但recv後沒有打印。

我在這裏錯過了什麼?

回答

4

一個可能的原因是send()不發送意圖的數據:

sent = send(sClient, cha, sizeof(cha) - 1, 0); 

sizeof(cha) - 1的實際上是sizeof(char*) - 1,而不是數據的實際長度:使用buffer.length()代替。

請注意,您可以在一個語句中使用字符串文字構造std::string,而不是通過多個連接構造它。然而,隨着std::string被用來獲得const char*唯一沒有理由使用std::string可言:

const char* buffer = "GET/HTTP/1.1\r\n" 
        "Host: http://www.yahoo.com/\r\n" 
        "Connection: close\r\n\r\n"; 

sent = send(sClient, buffer, strlen(buffer), 0); 

檢查的send()recv()返回值來決定成敗,尤其recv()的結果是被用來索引一個數組。在失敗時,recv()返回SOCKET_ERROR哪(我認爲)是-1


正確處理HTTP響應需要付出極大的努力。接收代碼需要檢查返回的HTTP headers以確定如何處理響應內容。例如,HTTP響應可能被分塊或不分塊。存在用於管理HTTP請求的庫,其中一個是cpp-netlib(2013年2月左右在isocpp.org上公佈)。

+0

由於代碼使用的是WinSock,因此它在Windows上運行,因此可以使用Microsoft的WinInet或WinHTTP API作爲直接使用WinSock的替代方案。 –

+0

在linux環境中使用函數時,我遇到了同樣的問題。我使用了sizeof,它使得recv函數可以被使用。現在我正在使用strlen,它按預期工作。 –