TCP 套接字异常断开和写入超时
我将尝试用最简短的语言解释这个问题。我正在使用 c++ builder 2010。
我正在使用 TIdTCPServer 并将语音数据包发送到已连接的客户端列表。一切正常,直到任何客户端异常断开连接,例如电源故障等。我可以通过切断已连接客户端的以太网连接来重现类似的断开连接。
现在我们有一个断开连接的套接字,但正如您所知,服务器端尚未检测到它,因此服务器也将继续尝试向该客户端发送数据。
但是,当服务器尝试向断开连接的客户端写入数据时…… Write() 或 WriteLn() 在尝试写入时挂起,就像在等待某种写入超时。这会挂起空洞数据包分发过程,从而导致向所有其他客户端的数据传输出现延迟。几秒钟后,出现“套接字连接关闭”异常,数据流继续。
这是代码
try
{
EnterCriticalSection(&SlotListenersCriticalSection);
for(int i=0;i<SlotListeners->Count;i++)
{
try
{
//Here the process will HANG for several seconds on a disconnected socket
((TIdContext*) SlotListeners->Objects[i])->Connection->IOHandler->WriteLn("Some DATA");
}catch(Exception &e)
{
SlotListeners->Delete(i);
}
}
}__finally
{
LeaveCriticalSection(&SlotListenersCriticalSection);
}
好吧,我已经有一个保持活动机制,可以在 n 秒不活动后断开套接字。但正如您可以想象的那样,该机制仍然无法与该广播循环完全同步,因为该广播循环几乎一直在运行。
那么我可以通过 iohandler 或其他方式指定写入超时吗?我已经看到很多关于“检测断开连接的 tcp 套接字”的线程,但我的问题略有不同,我需要在写入尝试期间避免挂起几秒钟。
那么有什么解决办法吗?
或者我应该考虑对此类数据广播使用某种不同的机制,例如广播循环将数据包放入某种 FIFO 缓冲区中,并且客户端线程不断检查可用数据并将其传递给自己?这样,如果一个线程挂起,它不会停止/延迟所有分发线程。
有什么想法吗?感谢您的时间和帮助。
问候
果酱
I will try to explain the problem in shortest possible words. I am using c++ builder 2010.
I am using TIdTCPServer and sending voice packets to a list of connected clients. Everything works ok untill any client is disconnected abnormally, For example power failure etc. I can reproduce similar disconnect by cutting the ethernet connection of a connected client.
So now we have a disconnected socket but as you know it is not yet detected at server side so server will continue to try to send data to that client too.
But when server try to write data to that disconnected client ...... Write() or WriteLn() HANGS there in trying to write, It is like it is wating for somekind of Write timeout. This hangs the hole packet distribution process as a result creating a lag in data transmission to all other clients. After few seconds "Socket Connection Closed" Exception is raised and data flow continues.
Here is the code
try
{
EnterCriticalSection(&SlotListenersCriticalSection);
for(int i=0;i<SlotListeners->Count;i++)
{
try
{
//Here the process will HANG for several seconds on a disconnected socket
((TIdContext*) SlotListeners->Objects[i])->Connection->IOHandler->WriteLn("Some DATA");
}catch(Exception &e)
{
SlotListeners->Delete(i);
}
}
}__finally
{
LeaveCriticalSection(&SlotListenersCriticalSection);
}
Ok i already have a keep alive mechanism which disconnect the socket after n seconds of inactivity. But as you can imagine, still this mechnism cant sync exactly with this braodcasting loop because this braodcasting loop is running almost all the time.
So is there any Write timeouts i can specify may be through iohandler or something ? I have seen many many threads about "Detecting disconnected tcp socket" but my problem is little different, i need to avoid that hangup for few seconds during the write attempt.
So is there any solution ?
Or should i consider using some different mechanism for such data broadcasting for example the broadcasting loop put the data packet in some kind of FIFO buffer and client threads continuously check for available data and pick and deliver it to themselves ? This way if one thread hangs it will not stop/delay the over all distribution thread.
Any ideas please ? Thanks for your time and help.
Regards
Jams
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Indy 中没有实现写入超时。为此,您必须使用 TIdSocketHandle.SetSockOpt() 方法直接设置套接字级超时。
FIFO 缓冲区是一个更好的选择(总体上也是一个更好的设计)。例如:
There are no write timeouts implemented in Indy. For that, you will have to use the TIdSocketHandle.SetSockOpt() method to set the socket-level timeouts directly.
The FIFO buffer is a better option (and a better design in general). For example: