|
Introduction
This article introduces an open source UDP-based data transfer library, namely UDT (UDP-based Data Transfer).
Currently, there are two major Internet transport protocols, TCP and UDP. TCP provides connection oriented reliable data streaming service, whereas UDP provides connection-less unreliable messaging service. Most applications use TCP to transfer data because they require data reliability.
However, when using TCP some applications suffer from two problems. First, TCP demonstrates poor performance in long distance links, especially when the bandwidth is high (e.g., 1GB/s or higher). Second, when incorporating multiple concurrent TCP flows with different RTTs in the same application, different TCP flows may have different data transfer rates (also known as RTT bias).
There are other situations where people do not want to use either TCP or UDP. For example, an application may require data reliability (so cannot use UDP directly) but also wants data to arrive at a user-controlled rate or the message boundaries to be conserved. Furthermore, sometimes it is easier to use UDP to traverse firewalls than TCP.
It may be helpful to build an open source user space transport protocol above UDP, but with the data reliability control and network flow/congestion control. Because it is at user space, it is easy to get installed. Because it is open source, it can be easily modified to meet various requirements from applications.
Example applications
Here we present two example applications in which you may need UDT.
a. Bulk data transfer and online streaming data processing
Suppose a company has their data stored in multiple branches around the world, each branch having its own part of the dataset. The datasets are very large (terabytes) and the company has a 1GB/s intranet to deliver them. Now one of its departments at Chicago branch wants to analyze its own dataset and the dataset of the London branch. This data analysis application will need to read two datasets (at London and Chicago, respectively) using the company's 1GB/s intranet to a computer at Chicago.
Recall the two problems of TCP mentioned above. First, the link must be extremely clean (very little packet loss) for TCP to fully utilize the 1GB/s bandwidth between London and Chicago. Second, when the two TCP streams (London->Chicago, Chicago->Chicago) start at the same time, the London-Chicago stream will be starved due to the RTT bias problem, thus the data analysis process will have to wait for the slower data stream.
b. Application awareness
A streaming video server is sending data to many clients. The server may choose a specific sending rate for each client during any specific period. You may have trouble asking TCP to send data at a fixed rate. And using UDP you have to do most of the data reliability control work by yourself. In addition, video frames are time sensitive data, if the frame is delayed too long, it will not be needed any more. That is, complete data reliability is not desired in this situation.
Using the UDT library, the programming work is simply several lines of option setting code.
UDT
UDT is a transport protocol with its own reliability control and flow/congestion control built above UDP. UDT provides both reliable data streaming service quite similar to TCP and partial reliable messaging. The latter allows users to send data as messages with specified delivery order and time-to-live value.
The position of UDT in the layered architecture of internet reference model is shown in the figure below. Applications use UDT socket to transfer their data, which is passed to the UDP socket. (Effort was made to avoid one time memory copy here.) A congestion control (CC) algorithm can be provided by applications; otherwise the default control algorithm is used. If user-defined control algorithm is provided, UDT will call the callback functions in CC once a control event occurs:

The default UDT control algorithm is designed for high performance data transfer over wide area high speed networks (e.g. in the case of example a). However, UDT's congestion control algorithm is configurable such that you can add your own control algorithm with ease (e.g., in the case of example b).
UDT provides a set of socket-like API. Using UDT in your application is simple as long as you are familiar with BSD socket. For example: With BSD socket, you write: int s = socket(AF_INET, SOCK_STREAM, 0);
Its counterpart in UDT is: UDTSOCKET u = UDT::socket(AF_INET, SOCK_STREAM, 0);
UDT is currently implemented using C++ and it supports Linux, Windows (2000, XP and above), and OS X. The current version is 3.0 Beta. After you download UDT, please read the "readme" file or the documentation for detailed installation and usage information. Note that if you are using Windows, you will need VC7 to get it compiled. With VC6, you will have to fix several incompatible C++ grammar by yourself.
If you are interested in the project, please refer to this site for more information.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 58 (Total in Forum: 58) (Refresh) | FirstPrevNext |
|
 |
|
|
Hi, I used UDT::select in a program, but it doesn't work the way it's supposed to. the server (use the UDT::select) listening on sockfd 3 for example, and then it only accept ONE connect(sockfd 4), after that all the listenning are base on sockfd 4, no sockfd 3 is listening. I checked the source code of UDT, and found that server listend on sockfd 3(stored in a variable called m_iSocket) in the very beginning, when the first connect is comming, server accepted it, and change the m_iSocket to 4, so any new connection could not connect to the server successful and will "time out" in the end. Is there anybody could give me a hand ?
..........
|
| Sign In·View Thread·PermaLink | 1.43/5 (4 votes) |
|
|
|
 |
|
|
 |
|
|
I am using the UDP-based Data Transfer Protocol with UDT-m/UDT v4, ! But sometimes it crashes in some map / vector functions inside the udt.dll ! I think it is a conflict with the Queue and Multithreading.
Did someone use the UDT-m and it works better?
- Jens Schneeweiß www.schneeweiss.de
www.schneeweiss.de
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I am currently working on a project and i am asked to "break" udt protocol from application, what i mean exactly is to make two different exes (one for protocol and one for application) and make them correspond with each other through pipes or something like that. I am newbie to newtwork programming so any help would be appreciated!
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hello lilyco, Hing,
I would like to understand if I can use multiple UDT sockets in parallel? I would like to maintain several (2-5) UDT connections at the same time. Is this possible? If not , would you please suggest me how to start to understand your code and how to add this feature?
Thanks a lot, Wee.
|
| Sign In·View Thread·PermaLink | 2.00/5 (5 votes) |
|
|
|
 |
|
|
Hi: I have a question about UDT, I see the document in http://udt.sourceforge.net/doc/index.htm which says : While UDT was originally written for extremely high speed data transfer, there are many other potential benefits from this reliable UDP-based library. One particular usage is to setup reliable connections between machines behind firewalls, especially those NAT firewall. To meet this requirement, UDT has added the rendezvous connection setup support. It seems UDT only support punching Firewall/NAT only in Rendezvous mode , is that right?
|
| Sign In·View Thread·PermaLink | 2.00/5 (3 votes) |
|
|
|
 |
|
|
Hello lilyco,
I need your suggestion. I want to understand the source code and want to add support to Rendezvous mode so that it supports "one port to multiple connections". I am a newbie to your code and would you think it is hard to do so? Or would you please suggest me how to start to understand your code and how to add this feature?
Thanks a lot. Hing
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
While it is not very difficult, there is no simple way to do it. First, you have to write a UDP multiplexer that deals with multiple connection sending and receiving. Once you have this ready, you can use it to replace the regular UDP channel as in channel.h.
I didn't use this method because it brings some additional overhead and it is not desirable in high performance computing area that UDT was originally designed for. I may use it in next UDT version if the overhead is proved to be very limited.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Thanks for your quick response, I just started looking at channel.cpp. However, I will have few questions before going further:
I found that you will have a "::connect" routine under UDP. Is that in Rendzvous mode, the "UDT::connect" will call the "::connect"? My concern is, since under UDP, if you call "::connect", it is just for one peer connection. According to the document of UNIX, "connect" under UDP mode only support one peer.
So, in order to support multiple connection for 1 port, either side should call connect, right? And go back to have connectionless design, but with your reliable messaging feature?
Or the design should be, still have connection-oriented design, but need one to be server which need to do bind->listen->accept action to accept connection under Rendezvous mode?
Or I still not yet fully understand your design? Coz I am just looking at your channel.cpp, not yet finished. I just want to tell some of my concern first and hope it may raise your awareness if there is any.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Sorry, as the thread is becoming large so, I post my question here:
Problem: While in rendezvous mode, when you do connect in a separate thread and the connect is blocking (waiting another to connect in), and you do UDT::close to close the socket which is being used in that thread by the "connect" function, the close function just blocked until the connection timeout in that thread.
Is that normal? Because I expect that whenever I call UDT::close, any socket operation should be abandoned and return immediately.
Also, are you working on the problem in the thread below? http://www.codeproject.com/internet/udt.asp?msg=1577366#xx1577366xx[^]
Thanks for your kind attention and I am looking forward to you.
Hing
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
In UDT, "close" does not return immediate but wait until other process (connect, send, recv, etc) to finish or timeout (see LINGER option). I did make a small change so that "close" will return very soon in the case you metioned. All the new code can be found in sourceforge CVS.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello lilyco,
I tried the following:
---------------------------------------------------------------- 1. A do: (INIT socket as SOCK_STREAM->Bind 9999->Listen 10->Accept->Recv if client connect)
2. B do: (INIT socket as SOCK_STREAM->Bind 8888->Connect 9999)
3. They connected and I tried to send message in between, it succeed.
4. If B is killed, A's "Recv" function doesn't return, and when A try to send message to the client B, it succeed (i.e. The "Send" function return ok), but I expect that it can detect the socket is broken.
5. After a minutes, A's "Recv" return: Error Code: 2001, Error Msg: Connection was broken --------------------------------------------------------------------
However, if i do "UDT::close" on B, the A can detect the connection broken immediately, is that I should always do "UDT::close"?
Thx a lot
-- modified at 23:20 Wednesday 12th July, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
In the first case, A uses timeout to detect the broken connection, because B is killed and A doesn't know. The time to detech broken connection varies, depending on the delay between A and B.
For a regular send, A simply copies the data into the protocol buffer and returns, so "send" does not know the error. If you use overlapped send, which wait until the data is actually sent to the peer side, it will detect the error.
In the second case, since you explicitly close B, which will send a shutdown msg to A before exit, A therefore will know it immediately.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello lilyco,
I have 1 questions:
I tried overlapped send by doing following: ----------------------------------------------------------------- ///// void DeleteBuf(char* buf, int a) { // do nothing } ///// int handle = 1; char buf[] = "hello"; if(UDT::ERROR == UDT::send(recver, buf, strlen(buf), 0, &handle, (UDT_MEM_ROUTINE)DeleteBuf)) { .... }
The "send" function return successfully even B is killed. -------------------------------------------------------
Thx a lot.
-- modified at 2:38 Thursday 13th July, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
sorry, my mistake. overlapped send will also return immediately unless the send buffer is full. You can use getoverlappedresult to check if the send if completed.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Sorry, I have question again.
I tried the following:
1. B: (INIT Sock as SOCK_STREAM->Set Rendevzous mode->Bind->Connect (waiting A)) 2. A: (INIT Sock as SOCK_STREAM->Set Rendevzous mode->Bind->Connect (connected to B)) 3. B exit 4. A try to send overlap with message "ABC", it return true, then, i call getoverlapresult as follow:
int progress; bool bwait = true; bool bResult = UDT::getoverlappedresult(udtsock, handle, progress, bwait);
The function just wait here. After a while, it return false with error code "0" and progress "0". But I expect that the error code shouldn't be zero and telling me why send fail.
I tried to set bwait as false, the function return false immediately with error code "0" and progress "0" again. But I expect that progress should be "-1" according to your documentation of "getoverlappedresult".
Thanks for your attention.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
If wait == true, then an error code should be returned. I have updated the code to reflect this change.
If wait == false, in the situation you metioned, A does not know the connection is broken yet, so A will return progress 0 (nothing is sent). If you try this call a moment later, once the broken connection is detected, progress should be -1.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello lilyco,
I would like to ask first if you will reply faster in codeproject forum or in sourceforge forum? As I saw someone post the same question in the sourceforge forum as well and you have a reply there, anyway, let me ask the question first:
In the help page of rendezous connection, I found that the information is not enough, for connection behind NAT, in the past, I would do like below using UDP:
1. For example, 192.168.0.2:5000 (named: A) wants to talk to 10.0.0.2:5000 (named: B) and both are behind NAT firewall.
2. There is a public known server 221.127.209.250 (named: C) which in otherwise stored the NAT address and port of A and B.
3. A and B go to the C to get the NAT address of each other
4. A try to send B a data using the NAT address of B and so, NAT router of A will build a NAT tuple (addr of A, port of A, addr of A's NAT, port of A's NAT, NAT addr of B, NAT port of B) (The data won't arrive as B's NAT didn't build the tuple yet)
5. B try to send A a data using the NAT address of A and so, NAT router of B will build a NAT tuple (addr of B, port of B, addr of B's NAT, port of B's NAT, NAT addr of A, NAT port of A)
6. Then, A and B can talk to each other by sending data using their NAT address and port. (As tuples are built in both NAT)
So, the above algorithm only work on UDP as only UDP can make sure both terminate use the fixed port (by using 'bind').
So, under UDT, what is the step we should do?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
1. create a UDP socket on A, bind to 5000, send any necessary message to C, so that C knows the the NAT address of UDP A:5000. 2. by the same way, C will know the NAT address of UDP B:5000. 3. close the UDP socket created in 1) and 2). 4. A and B obtain the other's NAT address from C 5. create UDT socket on A, bind it to 5000, set UDT_RENDZEVOUS option to true 6. do the same thing on B 7. On A, use UDT connect call to connect to the NAT address of B; On B, use UDT connect call to connect to the NAT address of A.
|
| Sign In·View Thread·PermaLink | 3.50/5 (2 votes) |
|
|
|
 |
|
|
Thx a lot, I didn't try yet, but I want to ask, in step 1, can I use UDT socket instead of UDP? Is there any different? Thx a lot.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello lilyco,
I am stuck in step 7. After I do all the things (step 1 to step 6), I tried to call connect, however, it just return saying that "connection timeout". I just wonder, in RENDZEVOUS mode, no one is able to call Listen or Accept, so, the "connect" function conceptually connect to nothing, right?
So, what can I do ... In fact, I tried in a public server and a machine under NAT below:
1. There is a public server (S) and a machine (A) under NAT.
2. I start a simple UDP server,S, in the public server.
3. A first bind (192.168.101.167:5000) and then connect to S using simple UDP connection and send some dummy message to S so that S get A's NAT address and port (123.123.123.123:19876)
4. I close the UDP connection in A and start UDT connection by doing: init socket as SOCK_STREAM->set rendezvous to 1->bind to the address (192.168.101.167:5000)
5. I start a UDT application B in the *public server* and do about the same thing: init socket as SOCK_STREAM->set rendezvous to 1->bind to a randome address (123.123.123.123:9000)
6. In B, I tried to connect to A by connecting to A's NAT address and port, but it return "connection timeout", and same thing happen in the side of A.
So, is that I missed some step ?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
RENDEZVOUS connect is different from the regular connect. In RENDEZVOUS mode, A and B have to connect to each other, i.e., they must both call "connect". If B connect to A while is doing nothing, then B indeed connect to nothing.
BTW, in step 1 & 2, you can use any methods to obtain the NAT address, including using UDT socket.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hello lilyco,
Thanks a lot. I succeed to connect to each other (ie Both "connect" return successfully ). However, I fail to send message to each other, what is the problem? I open the socket using SOCK_STREAM, and send a message "hello" by using the same UDTSOCKET in the whole procedure (i.e. Init the socket->Set Rendezous->Bind->Connect).
After connection succeed, I call recv, the function is blocking and waiting for message, the other side try to send message by using "send", the send function return successfully. However, in the receiving side, nothing received (i.e. the "recv" function never return).
After a while, the "recv" function return with the following error:
Error code:2001 Erro msg: Connection was broken
and when the other side try to send data to the receiving side, the "send" fail with the above error also.
So, when I do all the step again, it succeed to connect, but fail to send and receive message. So, what is the problem?
Thx a lot
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, thanks for the information. I just checked the code and found out that my recent changes had introduced a new bug for rendezvous connection. I have fixed it now. Please check out the new code from sourceforge CVS area and try again.
-- modified at 1:57 Wednesday 12th July, 2006
or, in core.cpp, make the following change.
+ 719 if (!m_bRendezvous) + 720 { 721 if (AF_INET == m_iIPversion) 722 addr4.sin_port = htons(res->m_iPort); 723 else 724 addr6.sin6_port = htons(res->m_iPort); + 725 }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|