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币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
UDT最新源代码下载链接
UDT源码下载地址:点击打开链接http://sourceforge.net/projects/udt/files/latest/download?source=directory.
UDT协议实现分析——UDT Socket的创建
UDT API的用法 在分析 连接的建立过程 之前,先来看一下UDT API的用法。在UDT网络中,通常要有一个UDT Server监听在某台机器的某个UDP端口上,等待客户端的连接;有一个或多个客户端连接UDT Server;UDT Server接收到来自客户端的连接请求后,创建另外一个单独的UDT Socket用于与该客户端进行通信。 先来看一下UDT Server的简单的实现,UDT的开发者
基于UDT connect连接通信以及文件传输
转自:http://blog.csdn.net/pingd/article/details/16341467 SERVER端 [cpp] view plaincopy #include    #include "udt.h"   #include       #pragma comment(lib,"ws2_32.lib")  
基于UDT connect连接通信以及文件传输--服务端
网上与UDT相关的资料不多,与UDT相关的源码例子更少。最近在接触UDT,也是因为缺少相关的资料,导致学习起来甚感痛苦。下面将我自己这两天弄出来的代码贴出来,希望对在寻找相关资料的童鞋有一定的帮助。         SERVER端 #include #include "udt.h" #include #pragma comment(lib,"ws2_32.lib") using nam
UDT协议详细介绍
基于UDP的数据传输协议(UDP-based Data Transfer Protocol,简称UDT)是一种互联网数据传输协议。UDT的主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。 顾名思义,UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向连接的双向的应用层协议。它同时支持可靠的数据流传输和部分可靠的数据报传
基于UDT connect连接通信以及文件传输--客户端
上面一篇文章中提出了服务端的,其实这里没有严格意义的服务端和客户端之分,因为我在代码中是基于UDP的,不存在服务端与客户端,两个都是对等的,只是我这里进行一下简单的区分而已。在这里,客户端所进行的主要操作就是首先给服务端发送文件名,然后将文件直接通过fopen(),fread()等一系列的操作将文件发送过去。         与客户端相对应的源码在另一篇博文中:http://blog.csdn.
UDT协议详解
基于UDP的数据传输协议(UDP-based Data Transfer Protocol,简称UDT)是一种互联网数据传输协议。UDT的主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。 顾名思义,UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向连接的双向的应用层协议。它同时支持可靠的数据流传输和部分可靠的数据报传
UDT协议学习笔记(一)UDT概述
UDT协议学习笔记(一)UDT概述 本人近来就职于国内某著名互联网血汗工厂,从事分布式后台相关的工作,最近的项目主要是网络相关。我们有许多海外的proxy节点,为了加速海外proxy与国内某机房的通信速率及抢占更多的带宽,于是开始调研一些udp based的应用层协议,如udt,quic等等。目前还处于调研状态中,尚未投入使用,这里算是分享下一些学到的东西,欢迎大家一起讨论~
UDT协议深入解析
将近两年以前因为想选择一个兼顾TCP协议的可靠性和UDP协议的高效性来进行我们某种数据的传输曾经选择过UDT协议,也进行了一段时间的学习、实践。但最终由于不适合我们的业务场景放弃了它,但它的实现原理、代码实现、拓展使用的优秀给我留下了很深刻的印象,今天翻出自己曾经的一篇总结笔记来和大家一起回顾下UDT协议。 UDT协议是什么?是一种基于UDP的数据传输协议(UDP-based Dat
UDT4协议源码分析之数据的发送和接收
协议分析 Data Sending and Receiving