我有一个使用POCO框架编写的C ++服务器应用程序。在这种情况下,服务器应用程序充当HTTP服务器。有一个客户端应用程序,我无法控制,无法调试,导致服务器出现问题。客户端请求一个大文件,该文件作为HTTP响应返回。在文件返回期间,客户端关闭连接。我看到套接字移动到CLOSE_WAIT状态,表明客户端已发送FIN。问题是在我的应用程序中,send()函数然后挂起导致我的一个HTTP线程基本上丢失,并且一旦所有线程进入此状态,服务器就没有响应。
发送代码在POCO框架内,但看起来像这样:
do
{
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
rc = ::send(_sockfd, reinterpret_cast<const char*>(buffer), length, flags);
}
while (_blocking && rc < 0 && lastError() == POCO_EINTR);
if (rc < 0) error();
return rc;
(调用此函数时标志为0)。我尝试通过添加以下代码来检测此状态:
char c;
int r;
int rc;
do
{
// Check if FIN received
while ((r = recv(_sockfd, &c, 1, MSG_DONTWAIT)) == 1) {}
if (r == 0) { ::close(_sockfd); _sockfd = POCO_INVALID_SOCKET; } // FIN received
if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException();
rc = ::send(_sockfd, reinterpret_cast<const char*>(buffer), length, flags);
}
while (_blocking && rc < 0 && lastError() == POCO_EINTR);
if (rc < 0) error();
return rc;
这似乎可以让事情变得更好,但仍然无法解决问题。我最终得到的服务器没有快速挂起,但更多CLOSE_WAIT套接字,所以我认为我已经部分解决了线程挂起问题,但我仍然没有正确地从破坏的套接字中整理好。随着这种变化,问题发生得越来越少,但仍然会发生,所以我认为关键是要理解为什么send()会挂起。
我正在linux上测试这段代码。
答案 0 :(得分:1)
要彻底关闭套接字:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// Set to new colour for whole app
UINavigationBar.appearance().barTintColor = UIColor.blueColor()
// Or, Set to new colour for just this navigation bar
self.navigationController?.navigationBar.barTintColor = UIColor.blueColor()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
//Revert to old colour, whole app
UINavigationBar.appearance().barTintColor = UIColor.redColor()
//Revert to old colour, just this navigation bar
self.navigationController?.navigationBar.barTintColor = UIColor.redColor()
}
致电shutdown
。您的代码有两个主要问题。它不会确保无论发生什么情况都始终在套接字上调用SD_SEND
,并且它可以在关闭套接字后访问套接字。前者导致您的CLOSE_WAIT问题。后者是一个巨大的安全漏洞。