2 congliu0913 congliu0913 于 2016.05.08 12:04 提问

UDT协议在连接对端时出错(UDT4.11 connect)

本人最近在研究UDT协议,想用它写一个Windows下运行的客户端,用c++编写,在写完测试时发现个问题,随后用UDE demo测试发现问题依然存在。(非Rendezvous模式)
运行环境:
Win7 VS2010 UDT版本4.11
问题描述:
因为是一个长期运行的程序,修改UDT demo recvfile.cpp 使它循环发送,不退出 对connect做如下处理
if (UDT::ERROR == UDT::connect(fhandle, peer->ai_addr, peer->ai_addrlen))
{
cout << "connect: " << UDT::getlasterror().getErrorMessage() << endl;

  UDT::close(fhandle);

  freeaddrinfo(peer);

  continue ;      

}
运行demo,让它连接一个不存在的IP,发现demo在运行几次后就会死掉,大约3次左右,使用VS2010调试,发现在死在UDT的接收线程里面,
CRcvQueue::worker(LPVOID param)函数的self->m_pRendezvousQueue->updateConnStatus();_而GC线程停在等待释放接收线程的位置。
再跟进去看发现是一个list的迭代器获取失败导致的,但是我没有找到有对这个容器的修改啊,希望有那个知道的大牛讲解下,万分感谢。

2个回答

congliu0913
congliu0913   2016.05.17 18:06
已采纳

果然还是要靠自己啊。
自己追踪了两天,发现是一个状态控制的原因,哪个list容器,原本应该在连接失败,调用close时被删除掉,但是因为(m_bConnecting)_的状态出现问题,
原本应是是true的,却变成了false。

if (m_bListening)
{
m_bListening = false;
m_pRcvQueue->removeListener(this);
}
else if (m_bConnecting)
{
m_pRcvQueue->removeConnector(m_SocketID);
}

猜测可能是recv 的work线程中的函数
// Check connection requests status for all sockets in the RendezvousQueue.
self->m_pRendezvousQueue->updateConnStatus();
将(m_bConnecting)_置为false(在超时的情况下)
// avoid sending too many requests, at most 1 request per 250ms
if (CTimer::getTime() - i->m_pUDT->m_llLastReqTime > 250000)
{
if (CTimer::getTime() >= i->m_ullTTL)
{
// connection timer expired, acknowledge app via epoll
i->m_pUDT->m_bConnecting = false;
CUDT::s_UDTUnited.m_EPoll.update_events(i->m_iID, i->m_pUDT->m_sPollID, UDT_EPOLL_ERR, true);
continue;
}
从而到时在connect失败是,调用close释放了UDT本身的空间,但是list却没有释放,而在list中有一个指针是指向UDT的空间的,而这个空间已经被释放,这样就会出错。
解决方案1:从根源解决
先释放list,在释放UDT时判断list是否释放,如果没有就释放。
解决方案2:简单解决
在connect失败后延时250ms以上,使(m_bConnecting)_得状态一定处于false,并改变删除list的判断条件,已false为释放出发点。
我用的是方案2,因为时间紧,目前未发现修改这个控制变量对其他地方的影响。

congliu0913
congliu0913   2016.05.26 16:36

最近有进一步研究发现 可以在connect超时时就把本次连接的套接字从临时会话队列中移除

if (CTimer::getTime() > ttl)
{
// Stop waiting for this connection
m_pRcvQueue->removeConnector(m_SocketID);

     // timeout
     e = CUDTException(1, 1, 0);
     break;
  }
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!