Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 12, 2009 9:37 PM
Hello Dukes!
Question:
Can someone please confirm that it is in fact possible to use java nio DatagramChannel in *connected mode* on Windows on a UDP server side, using non-blocking channels select(), with multiple UDP clients+?
I have code running on Linux as expected, but on Windows it is just bizzare;
It seems the bootom line question is:
Situation:
1) imagine you have 2 DatagramChannel s;
2) both channels are bound to the same localAddress;
3) both have socket.setReuseAddress(true);
4) first DatagramChannel is CONNECTED via channel.connect( remoteAddress );
5) second DatagramChannel is NOT connected;
6) now UDP packets start to arrive from the remoteAddress;
7) what happens? which channel will receive the packet, if at all? how select() will react? etc?
My experience is like this:
Linux answer:
a) first channel, that is, CONNECTED channel - will receive the packet and will activate select() with key.isReadble() for all traffic comming from the remoteAddress;
b) all other traffic NOT coming from the remoteAddress (that is, from NOT connected senders) will be received by the second channel, and it will also activate select() and key.isReadble()
appropriately;
Windows answer:
random bizzare patterns; namely:
1) sometimes first channel receives the packet
2) sometimes second channel receives the packet
3) sometimes both channel appear to hang and do not respond to any kinds of packets - coming from either remoteAddress or otherwise;
Windows workaround:
of course, one can go back to NON connected channels, but then you can really have only SINGLE DatagramChannel on the server, servicing multiple clients, which is not the NIO way.
NOTE:
I tried this on both JDK6 and JDK7, on multiple Linux flavors as well as Windows XP, 2000 and 2003; nio on Linux consitently works; nio on Windows - concistently NOT. Also, I tried numerous permutaions (about 7 different nio patterns) in the way select() / register() / interestOps() are managed; result is all the same, Linux works, Windows does not; I am at the point where I will need to try this code in C# to see if this is java or Windows problem; and I hope your answer can save me form this :-)
Any answer or experience you have would be greatly appreciated;
Re: Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 12, 2009 9:38 PM
(reply 1
of 13) (In reply to
original post )
Helpful
Can someone please confirm that it is in fact possible to use java nio DatagramChannel in *connected mode* on Windows on a UDP server side, using non-blocking channels select(), with multiple UDP clients+?
If only the clients connect to you. If your server connects its socket to one client, you won't get any data from any other client.
Situation:
1) imagine you have 2 DatagramChannel s;
2) both channels are bound to the same localAddress;
3) both have socket.setReuseAddress(true);
4) first DatagramChannel is CONNECTED via channel.connect( remoteAddress );
5) second DatagramChannel is NOT connected;
6) now UDP packets start to arrive from the remoteAddress;
7) what happens? which channel will receive the packet, if at all? how select() will react? etc?
I would expect both channels to receive data, and I would expect the Selector to detect OP_READ on both channels.
of course, one can go back to NON connected channels, but then you can really have only SINGLE DatagramChannel on the server, servicing multiple clients, which is not the NIO way.
Yes it most certainly is the NIO way. It is in fact the UDP way, for servers, NIO or not. I don't know where you got this idea from. You only ever need one datagram socket at the server.
The server shouldn't use > 1 datagram socket, and it shouldn't connect.
Otherwise you face for example the problem of when to disconnect at the server, and if you don't solve that you will get resource leaks.
I don't know where you got this model from but it is unnecessary and just causes more problems.
Re: Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 12, 2009 10:01 PM
(reply 2
of 13) (In reply to
#1 )
ejb, hi;
Thank you very much for the answer;
As you have probably guessed from the original post, I am trying to emulate TCP in UDP;
Namely:
1) I use single NON connected UDP channel as "acceptor" (think as if TCP ServerChannel);
2) when new / unknown remoteAddress packet arrive, I creage new DatagramChannel and CONNECT it to this new remoteAddress; this is how it is NOT preventing the "acceptor" to continue to accept;
3) this newly created/connected channel becomes "UDP session" (think as if TCP SocketChannel), while "acceptor" is ready for new clients;
To me this seems the "right NIO way", since each client has its own buffers, etc. - would you agree?
I also demonstrated that this works as described on Linux (with unbeatable performance);
Re: Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 12, 2009 10:10 PM
(reply 3
of 13) (In reply to
#2 )
Helpful
As you have probably guessed from the original post, I am trying to emulate TCP in UDP
Obviously. The question is why? There is just no point to all that. A single datagram socket is all you need.
2) when new / unknown remoteAddress packet arrive, I creage new DatagramChannel and CONNECT it to this new remoteAddress; this is how it is NOT preventing the "acceptor" to continue to accept;
Nothing prevents the 'acceptor' from continuing to accept. This step is completely unnecessary.
To me this seems the "right NIO way", since each client has its own buffers, etc. - would you agree?
No, I wouldn't agree. I've already explicitly disagreed above. I've already said what I consider the 'rght NIO way' and this isn't it. Using > 1 datagram socket in a server is just wasteful and causes more problems. You do need a ByteBuffer per incoming IP address. That's not hard to organize: Map<SocketAddress, ByteBuffer>.
I just need little help with Windows;
No, you just need to do it the easy way frankly. Especially as it doesn't work now. Even if you get this working on Windows you will then run into the other problem I mentioned. And more.
Re: Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 12, 2009 11:18 PM
(reply 5
of 13) (In reply to
#4 )
1) performance via multiple cpu doing multiple selectors / multiple datagram channels
Unaffected by your choice. And you don't need multiple selectors in any scenario unless you know you're going to have multiple CPU cores, in which case there might be some point to them. But that's orthogonal to what we're discussing here.
2) no overhead on security checks, etc in DatagramChannelImpl
True but minor. You will be I/O bound. Specifically, you will almost certainly be read-bound.
3) client "fairness" in the sense - if the application is IO bound, time delay between send to client #1 and client #1001 will be random
It's random anyway, unless your idea of my recommended implementation is different from mine, which I can't do much about.
4) same code base for TCP and UDP
Pointless. They're not the same, and forcing them to be the same just convolutes the architecture, as you're finding, and causes problems where they don't mesh, as you're also finding. If you really want the same codebase, use new Socket(host, port, false) and streams, and your code will really be the same. (And yes I know it's deprecated.)
It seems you experience speaks only for "single udp channel" for "multiple udp clients" approach
You clearly know nothing about my experience, but it seems to me that you're not interested in taking the advice you're given here. If so, why post?
Can you please confirm if this scales well into 1K ... 10K of clients?
I'm not interested in even discussing it. It's not working; you've been advised against it; and you've been told that it will cause you further problems down the track. What exactly is the problem here?
Can you reference any articles / benchmarks on the web?
Re: Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 13, 2009 7:52 AM
(reply 6
of 13) (In reply to
#5 )
ejp, hello,
regarding your answers:
1) "multiple CPU cores " --- yes, I plan on using to have multiple CPU cores, multipleselectors, and hopefully, multiple DatagramChannel s;
2) "True but minor " --- OK, thank you;
3) "idea of my recommended implementation" --- I would appreciate if you can elaborate a bit on your recommended implementation;
4) ...
a) "it is pointless to use same code base for TCP and UDP" --- probably you are right; BUT if you take a look on things like Apache MINA, and even JDK7 NetworkChannel, there seems to be an undying desire to deepen the abstraction of networking API; I just happen to be part of this "trend", sorry :-)
b) "You clearly know nothing about my experience" --- of course, your are right, I dont, but I am eager to learn, if you share, and yes, I am listening, and that is why I ask again:
I) can you please confirm if say 1K clients can be realistic on a single non-blocking NON connected DatagramChannel, as you suggested?
II) is it possible to use multiple CONNECTED DatagramChannel
s in OP_READ mode on Windows - as I suggested?
III) is it possible to use multiple NON connected DatagramChannels for both OP_READ and OP_WRITE at the same time - as an extension of your
design suggestion?
c) "I refer you toFundamental Networking In Java. " --- thank you for the reference; I have already read Fundamental Networking in Java, Introduction to Network Porramming in Java, Java Network Programming and Distributed Computing, Java NIO, Developing Applications using Java NIO, etc, etc; all these books are very good for TCP, but not so much for UDP; that is why I am on this forum;
//
Finally, let me mention that I think I understand you "good and proven" design advice, and in fact, that is what I am implementing right now as aresult of your answers- thank you! BUT I just happend to think that I have invented a better mouse trap; and in this context, your advice calls for merely giving up on it without trying any futher and I am not ready to let it go - as yet - especially after I have proved it to work great on Linux! :-)
Re: Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 13, 2009 7:12 PM
(reply 7
of 13) (In reply to
#6 )
3) "idea of my recommended implementation" --- I would appreciate if you can elaborate a bit on your recommended implementation;
A Selector. A thread. A select loop. When you get OP_READ on a channel, read the data and dispatch the work to a worker thread. When the reply is ready to be sent, send it, from the worker thread. If that returns zero, queue the reply to the selector thread and register OP_WRITE. The select loop should process OP_WRITE by reading this queue and writing it. If any of these writes returns zero it should return that write to the queue and cease processing OP_WRITE, otherwise if it empties the queue it should deregister OP_WRITE. The order of writes is determined by the order the worker threads can prepare the replies. It is essentially random. Nothing unfair about it.
a) "it is pointless to use same code base for TCP and UDP" --- probably you are right; BUT if you take a look on things like Apache MINA
Apache Mina isn't the greatest thing ever designed. Somewhere in these forums you'll find my critique. And unless it handles UDP by using multiple datagram sockets, it isn't an example of your 'trend' in the first place.
and even JDK7 NetworkChannel
This is just a parent interface for multicasting. It's not a generic framework that 'deepens the abstraction of networking API' or compels you to use unnecessary UDP sockets.
So I question whether the trend you mention really exists. In any case when you put as much effort into designing application frameworks as I have over 30+ years, you learn that it doesn't pay to abstract too far away from the underlying realities. You just end up allocating resources, such as redundant datagram sockets, artificially to fit into your own framework. Which is the opposite of the right idea.
I) can you please confirm if say 1K clients can be realistic on a single non-blocking NON connected DatagramChannel, as you suggested?
1K clients is realistic in practically any server architecture.
II) is it possible to use multiple CONNECTED DatagramChannel
s in OP_READ mode on Windows - as I suggested?
Apparently not.
III) is it possible to use multiple NON connected DatagramChannels for both OP_READ and OP_WRITE at the same time - as an extension of your
design suggestion?
I don't see why not, but I don't see why either.
thank you for the reference; I have already read Fundamental Networking in Java
Well I wrote it.
I just happend to think that I have invented a better mouse trap; and in this context, your advice calls for merely giving up on it without trying any futher
My advice calls for taking my advice.
But you haven't invented a better mousetrap, because it uses N sockets for N clients where my way you use 1. This has to be better. It can't not be.
Re: Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 14, 2009 8:16 PM
(reply 8
of 13) (In reply to
#7 )
Esmond, hello!
A Selector. A thread. A select loop ... Nothing unfair about it.
Thank you for sharing; this is exactly how I implemented it; I guess, You can call me a good student :-)
Apache Mina isn't the greatest ... in these forums you'll find my critique.
I looked around, but could not find this critique; if you can, please share a link?
I have over 30+ years, you learn that it doesn't pay to abstract too far away from the underlying realities.
Yes, you are right, but, I guess, I am still too young at heart! :-)
Apparently not .... I don't see why not, but I don't see why either ...
I think I found an answer from Microsoft: a) NO, can not use two UDP channels, one connected, one NON connected, bound to the same end point and expect them to listen "in a rational way" (as Linux does); b) NO, can not use multiple UDP channels bound to the same end point and expect them to take turns on receive; MSDN: http://msdn.microsoft.com/en-us/library/ms740618.aspx
Well I wrote it.
Wow! Congratulations! This is the best java book on networking I have read on the subject. Thank you so much for creating this book; it really is a life saver for me. I also found it rather funny, not sure if it was your original intent; "Computers cannot predict the future" - is my favorite line. :-)
My advice calls for taking my advice.
OK! I'll take it! Sold! I have already taken - Thank you.
But you haven't invented a better mousetrap...
Yes, you are right, your mousetrap is more effective, but mine is still more beautiful :-)
Thank you very much for all your time and answers; I learned a lot!
Re: Connected UDP channels? DatagramChannel.connect(...) Linux vs Windows
Apr 18, 2009 9:44 AM
(reply 12
of 13) (In reply to
#11 )
Esmond, hello;
Thanks for the links!
1) yes, your critique of MINA totally makes sense;
hopefully they will fix most of the things you mention
in MINA 3 - per MINA forums;
2) in one of the referenced posts you also mentioned
you are working on NIO framework yourself;
can I ask if it is available for the asking? :-)
Just to take a look, you know...
3) out of many NIO frameworks floating around,
can you please name 1 or 2 that you like most, and why?
When you register a channel, supply the appropriate one of these as the attachment. You only need one of them registered at a time. In the select loop, just cast the selection key's attachment to NIOHandler and call NIOHandler.handle(key) on it. Done.
What's inside the various handle() methods is either trivial or application-dependent. For example the AcceptHandler only needs to get the ServerSocketChannel, call accept(), and register the resuting SocketChannel for OP_READ or OP_WRITE as appropriate, with the appropriate NIOHandler attachment.
My framework was based on that with a large number of handlers, e.g. that would read a channel and write to a file, or read a file and write to a channel, and the aim was ultimately to get to a set of handlers that would support an FTP server, but once you start abstracting too far away from the realities it gets too complicated, e.g. where should I get the next handler from? so there was a NextHandlerFactory for each handler, all that kind of jazz, and it got pretty incomprehensible. I decided it was better for applications to write their own handlers and stay close to the metal.