首页 > 代码库 > Delphi / C++ Builder 使用 UDT ( UDP-based Data Transfer ) 4.11
Delphi / C++ Builder 使用 UDT ( UDP-based Data Transfer ) 4.11
添加 src/*.cpp 到工程, 修改 Directories and Conditionals, 添加 WIN32 UDT_EXPORTS
udt.h 需要 #pragma link "Ws2_32.lib"
common.cpp
channel.cpp
#elif WIN32 ---> #elif defined ( WIN32 )
http://www.cnblogs.com/littlestone08/archive/2011/12/17/2291194.html
在Delphi中使用UDT
UDT是用UDP实现,以可靠传输为目标的一套开源库,其源码可以在SF上找到,直到现在不久,才发现是它是国人的一个开源软件,向研究此协议的谷博士致敬,在当前的浮燥环境,尤其可敬。
网上有SDK作者本人写的一个DELPHI的UDT.pas的头文件,本来想用它来封装一个类似TTcpServer和TTcpClient的组件,但半途中发现udt的select函数的参数是C++中的Vector类型,这在Delphi中没有,而UDT.pas中也没有相关的定义。于是自己动手,丰衣足食,自己下载下来代码,手动重新导出已有的函数,新加并导出必要的函数。
关于编译SDK
对C++不熟悉,虽然网上有相关的讨论,也有答案,但还是费了点波折。关于编译 UDT SDK 4.9,用VS编译很顺利,但是用BCB则会出现一些情况。
(1)源码中没有BCB相对应的工程,可以直接新建立一个工程,直接加入所有的SDK源文件即可。
(2)通过看源码可以知道,如果要编译DLL库,则需要定义WIN32和UDT_EXPORTS两个编译条件变量。
(3)不设置UDT_EXPORTS的时候,可以编译成功,但如所料,没有导出函数,此时仅能供C++开发环境调用。但是设置后,编译将出错,BCB提示的大意是在channel.obj找不到xxxx函数,有很多条,都是和winsock相关的。解决的办法是,在channel.cpp中加入#pragma link "ws2_32.lib"指示字,即可正常编译.
(4)还有一个,就是#if ....#elif条件编译,好像BCB对其中的几个不认识。到时候如果需要编译,你把它改成#if ...#else if这样的形式就好了
(5)缺少一些函数,比如select函数所使用的Vector向量对象,函数也不是用stdcall方式导出的,另外,获得错误的函数是一个返回C++对象的引用,Delphi也是无法处理的。可以自己另写一个单元专门用来导出函数,在所提供的下载文件中,这个文件是udt2.h和udt2.cpp,直接把它们加到BCB的工程中就可以了
关于控件
为了便于使用,按照Delphi自带的Sockets单元中,重新抄了一份,名称为U_UdtSockets.pas,这基本上Sockets.pas相同,不同的是不是使用Winsock的API,而是使用udt.dll提供的API,来实现UDT的功能,而用法则和TcpServer和TcpClient相同。
值得注意的是,UDT支持Stream方式和Diagram方式两种,虽然叫Diagram,但实际上还是面向连接的,只是收发的时候调用的函数不同,收发的数据块有点限制。这个可以在组件中设置。我忘了我的默认是什么了,组件中有一个Socket的类型,可以设置为stStream或stDigram,据我的测试,使用时两者的区别并不大。不过,既然给了Diagram方式,我感觉可能对于非连续的数据应该这种方式比较好点。
提供的测试例子
里面有个测试的例子,包括Client和Server,后来为了方便,把两个界面弄成了一个界面,目录为Merger。当然这个小例子的界面不怎么友好,因为只是为了自己测试组件的,自己懂就好了,如果需要的话,看看代码,应该没有什么困难。
提供的下载
下面的代码仅在Delphi2007中编写,由于早期版本有一些常数并没有定义,如果在早期的版本上有错误,可以把版本中的常数定义搬过来,组件的代码逻辑应该是没有什么问题的,因为这是抄Sockets来的,嘿嘿,
最后需要谢谢〈因何糊涂〉朋友,本人没有用过C++,只是对其停在基本的层面上,在此期间,〈因何糊涂〉被我打扰了好多次,嘿嘿
源码下载地址(D7,D2007,XE2测试通过)
1.已经加上了编译好的DLL和BCB2007时编译的BCB源码
2.应评论,为了在XE2下能用,改动了一下,其实也很简单,毕竟没有对字符串的复杂的操作,把PChar改成PAnsiChar就可以了,然后就是两个函数EndWithText和EndWithStr,这两个函数其实是在StrUtils下面复制过来的,因为D5的版本没有Sockets.pas和StrUtils.pas等很多实用的单元,所以从这些单元中直接复制过来一些定义,然后就是这两个函数,好处就是可以在D5这样比较老的环境下编译。
这EndWithStr和EndWithText两个函数主要是在Sendln和Receveln中使用,由于UDT中没有PeekBuf函数,所以这两个函数的效率比较低,故不推荐用Sendln和ReceveLn这两个函数
评论有朋友说XE下不能编译和运行不正常的情况,后来发现朋友编译的EXE确实存在发送文件后,不能发送信息,而且速度很慢,服务端端口报错的情况,但是我用XE2编译后,没有发现这样的情况,这个我就不知道了。当然这个小DEMO的好坏不影响UDT本身的功能,这个DEMO也只是作为参考的,需要测试的话可以用这个EXE来对比。我在100M局域网,WINXP物理机用这个DEMO,发送1.6G的文件,速度平均6.5M/S,注意,用虚拟机测试速度可能差别很很大,比如我用我的虚拟机中WIN2003和WINXP,速度差也几倍