|
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.
|
|
|
|
|
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.
|
|
|
|
|
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
|
|
|
|
|
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.
|
|
|
|
|
Hello lilyco,
I tried the following:
----------------------------------------------------------------
1. A do: (INIT socket as SOCK_STREAM->Bind <localhost> 9999->Listen 10->Accept->Recv if client connect)
2. B do: (INIT socket as SOCK_STREAM->Bind <localhost> 8888->Connect <localhost> 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
|
|
|
|
|
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.
|
|
|
|
|
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
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
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?
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
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 ?
|
|
|
|
|
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.
|
|
|
|
|
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
|
|
|
|
|
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 }
|
|
|
|
|
|
Hello lilyco,
Ummmm ... I have too many questions ...
I got the following problem:
------------------------------------------------------------
1. Machine A do the following:
(Init sock as SOCK_STREAM->set rendezvous->Bind 192.168.101.167 8888->Connect 192.168.101.168 9998)
2. Machine B do the following:
(Init sock as SOCK_STREAM->set rendezvous->Bind 192.168.101.167 9999->Connect 192.168.101.168 8888)
(Notice that I set A connect to '9998' but B bind to '9999')
3. A immediately return:
ErrorCode: 1004, ErrorMsg: Connection setup failure: abort for security reasons
4. B keep waiting for connection.
----------------------------------------------------------------
Then, whenever A try to connect to 9998, it keep returning the same thing, however, if A change to connect to '9999' now, everything is fine.
So, is it a problem? What mean of the error? What should I do if i get this secrutiy error?
Thanks a lot
-- modified at 4:14 Wednesday 12th July, 2006
|
|
|
|
|
Because A tries to connect to 9998, but receives something from 9999, which is very likely an attack. The two peers of rendezvous connect must match. Of course, if you dont like this feature, it is very easy to remove it by disable the proper code in core.cpp/connect().
|
|
|
|
|
I tried following:
1. A: (init socket as tcp->set rendezvous->bind->connect (waiting B))
2. B: (init socket as tcp->bind->connect (A "connect" return successfully, but B "connect" function return saying that security problem))
(Notice that I didnt' set B in rendezvous mode, and both do connect)
I expect A will *NOT* return successfully, but it return succeed. However, if I do send on A, the "send" function will return false saying that Invalid Socket ID (5004).
Is that a problem? Or that is the user responsibility to check that if the connection is valid by issue a "send"?
Similiar problem happen if A do (init sock->bind->listen->accept) but B do (init sock->set rendezvous->bind->connect), A's "accept" return successfully and B's "connect" return successfully too. However, they both fail to send message to each other.
So, is that a problem? If not, what extra step I should do to ensure that the Accept and Connect return is a valid return?
Thanks for your attention.
-- modified at 5:59 Friday 14th July, 2006
|
|
|
|
|
Also, will the later version support multiple connection on one port under rendezvous mode?
Thx a lot
|
|
|
|
|
very possible. I am considering it. It is not hard to support this, but I am weighing the additional processing overhead.
|
|
|
|
|
hello,i can not find "the new code from sourceforge CVS area", and either not find the code in core.cpp
721 if (AF_INET == m_iIPversion)
722 addr4.sin_port = htons(res->m_iPort);
723 else
724 addr6.sin6_port = htons(res->m_iPort);
there are not any code including addr4.sin_port or addr6.sin6_port ,please help me! Thank you very much!!!!
matrix
|
|
|
|
|
Also, If I try this in the same machine (i.e. Initsocket as SOCK_STREAM->Set Rendzvous->Bind->Connect), the two nodes succeed to connect, but fail to send and recv by showing the same error.
|
|
|
|
|