HttpSendRequest und Timeout



  • Hallo,

    ich habe ein komisches Problem mit HttpSendRequest().
    Am Anfang wenn ich meine Applikation starte, funktioniert alles gut. Von mehreren Stellen (und auch Threads) werden Verbindungen erfolgreich aufgebaut. Nach einiger Zeit jedoch bekomme ich einen Timeout wenn ich was über HttpSendRequest() senden möchte (was in httpSendRequestThread.Start() als Thread passiert).
    Z.b. die ersten 100 Requests (oder so) sind ok, ab dann bekomme ich immer einen Timeout. Da ich gegen verschiedene Server gehe, dürfte es nicht sein, das der Server blockiert. Sobald ich die Applikation beende und wieder neue starte, funktioniert wieder alles... für die ersten 100 Requests.

    Meine Vermutung ist nun, das ich etwas nicht richtig schließe. Irgend ein Handle oder so...

    Hier mal der Code.
    httpSendRequestThread ist nur eine Klasse die HttpSendRequest() ausführt und den Thread beendet wenn er fertig ist. Das mache ich um den Timeout steuern zu können.

    SallyAPI::Network::NETWORK_RETURN NetworkHelper::GetHTTPText(const std::string& server, int port, 
    															 const std::string& request, int* byteRead,
    															 std::string* response, const std::string& proxy,
    															 const std::string& proxyBypass,
    															 DWORD iFlag, int timeoutSeconds,
    															 std::string* headerData, std::string* postData)
    {
    	HINTERNET connection = NULL;
    	HINTERNET httpConnect = NULL;
    	HINTERNET httpRequest = NULL;
    
    	if (proxy.length() == 0)
    		connection = InternetOpen("SallyAPI", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    	else
    		connection = InternetOpen("SallyAPI", INTERNET_OPEN_TYPE_PROXY, proxy.c_str(), proxyBypass.c_str(), 0);
    
    	if (connection == NULL)
    	{
    		LogNetworkError(server, port, request, ERROR_PREPARE);
    		return ERROR_PREPARE;
    	}
    	httpConnect = InternetConnect(connection, server.c_str(), port, "", "", INTERNET_SERVICE_HTTP,0,0);
    	if (httpConnect == NULL)
    	{
    		InternetCloseHandle(connection);
    
    		LogNetworkError(server, port, request, ERROR_PREPARE);
    		return ERROR_PREPARE;
    	}
    
    	std::string sendMethod = "GET";
    	if (postData != NULL)
    		sendMethod = "POST";
    
    	httpRequest = HttpOpenRequest(httpConnect, sendMethod.c_str(), request.c_str(), NULL, NULL, NULL, iFlag | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_PRAGMA_NOCACHE, 0);
    	if (httpRequest == NULL)
    	{
    		InternetCloseHandle(httpConnect);
    		InternetCloseHandle(connection);
    
    		LogNetworkError(server, port, request, ERROR_OPEN);
    		return ERROR_OPEN;
    	}
    
    	DWORD dwFlags;
    	DWORD dwSize = sizeof(dwFlags);
    
    	InternetQueryOption(httpRequest, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&dwFlags, &dwSize);
    	dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
    	InternetSetOption(httpRequest, INTERNET_OPTION_SECURITY_FLAGS,
    		&dwFlags, sizeof(dwSize));
    
    	DWORD	reqget = 20;
    	char reqReceive[20];
    
    	CHttpSendRequestThread httpSendRequestThread;
    	if (postData != NULL)
    		httpSendRequestThread.SetValues(httpRequest, *postData);
    	else
    		httpSendRequestThread.SetValues(httpRequest);
    
    	httpSendRequestThread.Start();
    
    	int millSeconds = timeoutSeconds * 1000;
    	do
    	{
    		Sleep(100);
    		millSeconds -= 100;
    	} while ((httpSendRequestThread.GetStatus() == SallyAPI::System::THREAD_RUNNING) && (millSeconds > 0));
    
    	if (httpSendRequestThread.GetStatus() == SallyAPI::System::THREAD_RUNNING)
    	{
    		InternetCloseHandle(httpRequest);
    		InternetCloseHandle(httpConnect);
    		InternetCloseHandle(connection);
    
    		httpSendRequestThread.Stop(true);
    
    		LogNetworkError(server, port, request, ERROR_HTTP_TIMEOUT);
    		return ERROR_HTTP_TIMEOUT;
    	}
    
    	HttpQueryInfo(httpRequest,HTTP_QUERY_STATUS_TEXT ,reqReceive,&reqget,0);
    
    	if (reqget == 0)
    	{
    		InternetCloseHandle(httpRequest);
    		InternetCloseHandle(httpConnect);
    		InternetCloseHandle(connection);
    
    		LogNetworkError(server, port, request, ERROR_NOTHING_READ);
    		return ERROR_NOTHING_READ;
    	}
    
    	char		buf[1001];
    	bool		readOk = true;
    	DWORD		dBytesReceived;
    	*byteRead = 0;
    
    	do
    	{
    		readOk = (InternetReadFile(httpRequest, &buf, 1000, &dBytesReceived) != 0);
    		if (dBytesReceived > 0)
    		{
    			buf[dBytesReceived] = '\0';
    			response->append(buf);
    			*byteRead += dBytesReceived;
    		}				
    	}
    	while (readOk == TRUE && dBytesReceived > 0);
    
    	if (headerData != NULL)
    		GetHeaderData(httpRequest, headerData);
    
    	InternetCloseHandle(httpRequest);
    	InternetCloseHandle(httpConnect);
    	InternetCloseHandle(connection);
    	return SUCCESS;
    }
    

    Auszug aus der CHttpSendRequestThread class:

    void CHttpSendRequestThread::RunEx()
    {
    	if (m_strPostData.length() == 0)
    		HttpSendRequest(m_pHttpRequest, 0, 0, 0, 0);
    	else
    		HttpSendRequest(m_pHttpRequest, "Content-Type: application/x-www-form-urlencoded", -1, (LPVOID) m_strPostData.c_str(), strlen(m_strPostData.c_str()));
    
    	m_iErrorCode = GetLastError();
    
    	return;
    }
    

    vielleicht liegt es auch am httpSendRequestThread.Stop(true). Hier wird dann ein TerminateThread(m_hThread, 0) aufgerufen um den Thread zu killen der gerade das HttpSendRequest() macht...

    Bruche ich HttpEndRequest()? Hatte ich früher nie verwendet... bin da jetzt aber drüber gestolpert.

    Noch als Info:

    WSAStartup() führe ich beim start der App aus (also nur einmal) und das WSACleanup() erst wenn ich die App beende.



  • niemand eine Idee?

    Dachte es ist ein Handle Problem - scheint aber nicht der Fall zu sein...



  • sorry, das ich den alten Thread noch mal ausbudle... hab aber immer noch keine Lösung gefunden 😞

    Kann mir jemand mal erklären wie ich richtig mit HttpSendRequest() umgehen, wenn ich nen timeout definieren will... finde überall Beispiele mit einen zweiten Thread (so läuft es bei mir jetzt auch). Weiss aber nicht ob das so ok ist...


Anmelden zum Antworten