【原创】基于UDP的可靠数据连接方式UDT C++Builder6下编译成功包【原创】

huzhangyou 2007-12-02 03:54:15
还是前面那个朋友公司的问题,可能在VS2003以及更高版本使用太成功顺利的感觉,要在C++Builder6下面编译,还费了偶不少时间哈!

需要注意的地方大概说一下,需要源码的可以联系我QQ或者MSN或者同我Email,我会在看到消息以后立刻发送给你。

1:需要在编译的头部定义
#define WIN32
2:部分#elif的地方需要注释并截取windows平台的代码

3:生成的lib文件需要包含使用,同时更加需要处理的是 将obj文件进行包含进工程,这是在我实在解决不了了以后,突然打开lib文件,发现里面仅仅是一堆obj文件,才想到的方法,真的是机缘巧合啊。

4:需要#pragma link "Ws2_32.lib"

最后编译就OK了


代码下载:

http://www.libing.net.cn/read.php/1449.htm
...全文
519 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
huzhangyou 2007-12-03
  • 打赏
  • 举报
回复
to DoorKey:

非常感谢你的回复

我想你还没有注意这段小小代码的设计方案:

注意里面的 TempListData: TList;
临界区只是进入到这里 就将所有的数据Copy出来了
然后立刻释放锁
然后线程去处理这个 TempListData: TList;

另外你所说的方案其实并没有考虑到过多的线程切换所带来的代价

当然可以采取线程池来处理
而你想想一下,如果队列里面 10条数据
只处理一个数据的话,这样锁的概率岂不是更大
期望继续跟帖

wg961423 2007-12-03
  • 打赏
  • 举报
回复
收藏学习中。。。。。。
DoorKey 2007-12-03
  • 打赏
  • 举报
回复
我觉得你的处理线程设计得有问题,你的代码如下:
procedure ExecuteCenterData.ExecuteData;
var
i,j:integer;
TempListData: TList;
begin
TempListData := TList.Create;
frm_Main.CS.Enter;//注意
for i:=0 to frm_Main.CenterMsg.Count-1 do
begin
TempListData.Add(frm_Main.CenterMsg[i]);
end;
frm_Main.CenterMsg.Clear;
frm_Main.CS.Leave;

for j:=0 to TempListData.Count-1 do
begin
//TempListData.Add(frm_Main.CenterMsg[i]);
//fuck now TempListData[j]
end;
end;
你看一下你的代码,是在一个处理线程一次取下所有已经接收到数据,这当然会造成这个处理线程长时间临界区,
我觉得应该开多个线程而一个处理线程一次只处理一个接收到的数据。这样可能相对会好一点。
僵哥 2007-12-03
  • 打赏
  • 举报
回复
> 据称在Windows的高版本当中有一个SinglyLinkedList,比较高效,具体的没有加以测试评估。

如果使用这个的话 是不是线程就不需要同步了?
================================
这个就是为提高线程访问共享数据的同步提升效率而设置的所谓“原子级”操作。
i_love_pc 2007-12-03
  • 打赏
  • 举报
回复
板凳听课中...
huzhangyou 2007-12-03
  • 打赏
  • 举报
回复
>曾经看MSDN的时候,好象有见到过一个未来版本(即Windows Vista/2008以后),有基于原子操作的队列,实现也是基于SinglyLinkedList.
这个我也听过

不过没有看到过相关资料

>也可以考虑使用TLS(Thread-local storage )。

我先看看TLS的资料,再来讨论 非常感谢

>据称在Windows的高版本当中有一个SinglyLinkedList,比较高效,具体的没有加以测试评估。

如果使用这个的话 是不是线程就不需要同步了?
僵哥 2007-12-03
  • 打赏
  • 举报
回复
曾经看MSDN的时候,好象有见到过一个未来版本(即Windows Vista/2008以后),有基于原子操作的队列,实现也是基于SinglyLinkedList.
僵哥 2007-12-03
  • 打赏
  • 举报
回复
除了资源池以及IOCP 有没有别的折中的方法
=========================
据称在Windows的高版本当中有一个SinglyLinkedList,比较高效,具体的没有加以测试评估。但是比较可惜,它是一个堆栈的模式,并且MSDN说是只在内核当中应用。相关的函数有:InitializeSListHead(初始化),InterlockedPushEntrySList(压栈),InterlockedPopEntrySList(出栈),InterlockedFlushSList(刷新)。

其他的暂时想不到更好的了。或者不需要多线程的同步,也可以考虑使用TLS(Thread-local storage )。这里要提一下的是,完成端口也可以当成是一个队列来用(FIFO),并且暂时也没有发现什么太大的瓶颈(当然不可能没有消耗)。
UDX协议 2007-12-03
  • 打赏
  • 举报
回复
udt在公网上效率不高。目前最新版本。
huzhangyou 2007-12-03
  • 打赏
  • 举报
回复
资源池

改天实现一个资源池发上来

IOCP实现倒不是难事
但是同样的问题 也还是数据进入临界区的问题

或许资源池 可以解决 具体的方案还要数据测试

to DoorKey:
>我们的目标是尽最大可能减少UDP监听线程被Enter挂起的次数。线程适量多是没有问题的。

这个我想你没有经过压力测试,我是专门做服务器开发的,问题你倒是也提出来了 只是解决方案没有

期待

to unsigned: 除了资源池以及IOCP 有没有别的折中的方法
僵哥 2007-12-03
  • 打赏
  • 举报
回复
比如“环”元素为N,设当前节点下标为Index,那么各线程索引到的节点就是:ThreadedIndex = InterlockedExchange(Index,(Index+1) % N),如果需要退节点就是:InterlockedExchange(Index,(Index+(N-1)) % N)。

对于这种分散同步的方法,个人觉得对于资源池也是一个比较好的方法。仅仅只是增加部分内存的消耗。在长期使用之后,基本上可以达到平衡。
僵哥 2007-12-03
  • 打赏
  • 举报
回复
普通的UDP包 能继续讨论一下如何避免吗?
=======================
UDP我也只是这两周才开始做个小小的东西。以前是同事写的,使用的是Indy,方法是开双线程。不过我所需要的业务比较简单,也不希望让它占用两它线程那么浪费。刚开始的时候,只是决定采用单线程非阻塞的方式,虽然没有进行验证,但是要么线程一直占用CPU资源,不断的检索收发(不习惯使用select)。基于应用当中众多地方都是采用IOCP来管理,顺便把很多任务的调度都放在其中。所以干脆就使用IOCP(我的应用比较简单,都是单包应用,不需要考虑拼接)。同时开多个WSARecvFrom,然后就不断地收发完事。多个WSARecvFrom轮询,基本上不会由于本地线程的“碰车”而导致丢包。

另外,最近在考虑一个问题就是类似于TimerWheel模式的同步管理。采用“同步环”,进行多路同步。比如说把“同步环”设置为N个“环节点”,然后根据不同的数据导入采用环境索引,从而可以达到多节点分散同步,来减少线程碰撞。
QSmile 2007-12-03
  • 打赏
  • 举报
回复
樓主,能不能把 UDT 做成標准 DLL 在 Delphi 下使用?
DoorKey 2007-12-03
  • 打赏
  • 举报
回复
你的代码在Enter后是用循环来把所有数据加到新创建的TempListData。哪怕就10条,这个也是很影响的。(我曾经用程序测试过)
frm_Main.CS.Enter;//注意
for i:=0 to frm_Main.CenterMsg.Count-1 do
begin
TempListData.Add(frm_Main.CenterMsg[i]);
end;
frm_Main.CenterMsg.Clear;
frm_Main.CS.Leave;

我们的目标是尽最大可能减少UDP监听线程被Enter挂起的次数。线程适量多是没有问题的。
huzhangyou 2007-12-02
  • 打赏
  • 举报
回复
to unsigned:

兄长对网络方面比较熟悉,这个问题你继续

我说一下我的问题:

我的问题并不是UDT引起的
而是普通的UDP引起的

就是普通的UDP包 能继续讨论一下如何避免吗?


UDP Socket 等待数据有数据来临 TCriticalSection CS;
CS-> Enter
//这里面把数据压入了List
CS-> Leave

这个List是全局的数据 在一个线程里面进行处理同样也是CS-> Enter
CS-> Leave
问题就出来了

当这个数据在线程里面Enter的时候 UDP Socket接收到数据 发现CS没有被释放
这个数据是不是直接被丢弃了
前提用的是Indy的UDP Socket
僵哥 2007-12-02
  • 打赏
  • 举报
回复
UDT的本意是为大文件传输而设计,而并不是高并发,所以存在并发阻塞,也在所难免。
huzhangyou 2007-12-02
  • 打赏
  • 举报
回复

有道理
只是 这个足够快只是一个概念词
如何保证呢?

怎么设计一个足够快的Cache
难道也设计一个Cache池?
ly_liuyang 2007-12-02
  • 打赏
  • 举报
回复
"数据都投递到了,而我数据队列忙,导致丢失"这也是UDP本来的缺陷
UDP Socket获取数据后,立即投递到应用层,不管应用层是否处理完,系统是不管的
所以你需要另外的Cache机制,这个Cache要足够快来处理,而且尽可能不存在阻塞
huzhangyou 2007-12-02
  • 打赏
  • 举报
回复
等待高人。。。
继续
huzhangyou 2007-12-02
  • 打赏
  • 举报
回复

constructor TThreadList.Create;
begin
inherited Create;
InitializeCriticalSection(FLock);
FList := TList.Create;
FDuplicates := dupIgnore;
end;

destructor TThreadList.Destroy;
begin
LockList; // Make sure nobody else is inside the list.
try
FList.Free;
inherited Destroy;
finally
UnlockList;
DeleteCriticalSection(FLock);
end;
end;

procedure TThreadList.Add(Item: Pointer);
begin
LockList;
try
if (Duplicates = dupAccept) or
(FList.IndexOf(Item) = -1) then
FList.Add(Item)
else if Duplicates = dupError then
FList.Error(@SDuplicateItem, Integer(Item));
finally
UnlockList;
end;
end;

procedure TThreadList.Clear;
begin
LockList;
try
FList.Clear;
finally
UnlockList;
end;
end;

function TThreadList.LockList: TList;
begin
EnterCriticalSection(FLock);
Result := FList;
end;

procedure TThreadList.Remove(Item: Pointer);
begin
LockList;
try
FList.Remove(Item);
finally
UnlockList;
end;
end;

procedure TThreadList.UnlockList;
begin
LeaveCriticalSection(FLock);
end;

{ TInterfaceList }

constructor TInterfaceList.Create;
begin
inherited Create;
FList := TThreadList.Create;
end;

destructor TInterfaceList.Destroy;
begin
Clear;
FList.Free;
inherited Destroy;
end;


上面的代码为系统的代码
从代码可以得知 也是通过TCriticalSection方式实现的
当然是TRTLCriticalSection
加载更多回复(9)

1,316

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧