我剛碰到同樣的問題,我想我已經爲您解決了問題。
正如您剛纔所說,問題在於gSoap掛在soap_serve上。發生這種情況是因爲gSOAP會爲您生成一個等待所有保持活動請求到達的內部循環,或者會出現服務器端的超時。
我所做的是抓取自動生成的服務存根中的soap_serve函數。我要列出原來soap_serve功能,讓你可以找到你的服務存根文件:
SOAP_FMAC5 int SOAP_FMAC6 soap_serve(struct soap *soap)
{
#ifndef WITH_FASTCGI
unsigned int k = soap->max_keep_alive;
#endif
do
{
#ifdef WITH_FASTCGI
if (FCGI_Accept() < 0)
{
soap->error = SOAP_EOF;
return soap_send_fault(soap);
}
#endif
soap_begin(soap);
#ifndef WITH_FASTCGI
if (soap->max_keep_alive > 0 && !--k)
soap->keep_alive = 0;
#endif
if (soap_begin_recv(soap))
{ if (soap->error < SOAP_STOP)
{
#ifdef WITH_FASTCGI
soap_send_fault(soap);
#else
return soap_send_fault(soap);
#endif
}
soap_closesock(soap);
continue;
}
if (soap_envelope_begin_in(soap)
|| soap_recv_header(soap)
|| soap_body_begin_in(soap)
|| soap_serve_request(soap)
|| (soap->fserveloop && soap->fserveloop(soap)))
{
#ifdef WITH_FASTCGI
soap_send_fault(soap);
#else
return soap_send_fault(soap);
#endif
}
#ifdef WITH_FASTCGI
soap_destroy(soap);
soap_end(soap);
} while (1);
#else
} while (soap->keep_alive);
#endif
return SOAP_OK;
}
你應該提取該函數的主體,並取代舊soap_serve(mySoap)你的線程裏面調用(
do
{
if (Server::mustShutdown()) {
break;
}
soap_begin(mySoap);
// If we reached the max_keep_alive we'll exit
if (mySoap->max_keep_alive > 0 && !--k)
mySoap->keep_alive = 0;
if (soap_begin_recv(mySoap))
{ if (mySoap->error < SOAP_STOP)
{
soap_send_fault(mySoap);
break;
}
soap_closesock(mySoap);
continue;
}
if (soap_envelope_begin_in(mySoap)
|| soap_recv_header(mySoap)
|| soap_body_begin_in(mySoap)
|| soap_serve_request(mySoap)
|| (mySoap->fserveloop && mParm_Soap->fserveloop(mySoap)))
{
soap_send_fault(mySoap);
break;
}
} while (mySoap->keep_alive);
請注意以下幾點:
- 服務器:: mustShutdown()作爲一個標誌,將是執行,因爲這些保活的有以下要求和hagns)螺紋小號等到真(外部)結束所有線程。當你想停止服務器處理新的請求時,你會使這個函數返回true並且循環結束。
- 我已經刪除了ifdef,WITH_FASTCGI這對我們現在不感興趣。
- 當你像這樣關閉連接時,連接到服務器的任何客戶端都會引發異常。例如用C#編寫的客戶端會拋出一個「底層連接被保留在活動中被服務器關閉」,這對我們來說非常合理。
但是,由於AudioComplex指出,我們尚未完成,系統仍然在等待soap_begin_recv上的請求。但我也有一個解決方案;)
連接處理池上的每個線程創建主soap上下文的副本(通過soap_copy),這些線程是我每次存儲的
這些上下文作爲駐留在主連接處理線程上的數組上的元素。 當終止主連接處理線程(即服務請求中的一個),它會「手動」的連接通過所有肥皂的上下文並最終確定使用:
for (int i = 0; i < soaps.size(); ++i) {
soaps[i]->fclose(soaps[i]);
}
這將迫使soap_serve循環來完成。它實際上將停止內部環路附近的stdsoap2.cpp_
r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
這是不乾淨的解決方案921線(還沒有找到一個更清潔的一個),但它肯定會停止服務。
首先,感謝您的回覆!但我認爲這不會解決我的問題。在你的解決方案中,調用soap_begin_recv()仍然會阻塞,直到發生超時或客戶端連接到套接字,對吧? – audiocomplex
嗨,在那裏,剛剛回答你的問題,希望它有幫助! – svives
謝謝,這確實解決了這個問題。非常感謝您的詳細解決方案! (對不起,我沒有長時間查看此線程......) – audiocomplex