My Java application receives data through UDP. It uses the data for an online data mining task. This means that it is not critical to receive each and every packet, which is what makes the choice of UDP reasonable on the first place. Also, the data is transferred over LAN, so the physical network should be reasonably reliable. Anyway, I have no control over the choice of protocol or the data included.
Still, I am concerned about packet loss that may arise from overload and long processing time of the application itself. I would like to know how often these things happen and how much data is lost.
Ideally I am looking for a way to monitor packet loss continuously in the production system. But a partial solution would also be welcome.
I realize it is impossible to always know about UDP packet losses (without control on the packet contents). I was thinking of something along the lines of packets received by the OS but never arriving to the application; or maybe some clever solution inside the application, like a fast reading thread that drops data when its client is busy.
We are deploying under Windows Server 2003 or 2008.
The problem is that there is no way to tell that you have lost any packets if you are relying on the UDP format.
If you need to know this type of information, you need to build it into the format that you layer ontop of UDP (like the TCP Sequence Number). If you do that and the format is simple then you can easily create filters into Microsoft's NetMon or WireShark to log and track that information.
Also note that the TCP Sequence Number implementation also helps to detect out of order packets take may happen when using UDP.
If you are concerned about packet loss, use TCP.
That's one reason why it was invented.
Related
This is a similar answer, though is not what I exactly want. I want to do following two things:
I want to find out if all the bytes have been sent to the receiver?
Also I want to know the current remaining capacity of output buffer of the socket, without attempting a write to it?
Taking your numbered points in order:
The only way you can find that out is by having the peer application acknowledge the receipt.
There isn't such an API in Java. As far as I know there isn't one at the BSD sockets layer either, but I'm not familiar with the outer limits of Linux where they may have introduced some such thing.
You cannot know. The data is potentially buffered by the OS and TCP/IP stack, and there is no method for determining if it has actually been placed on the wire. Even knowing it was placed on the wire is no guarantee of anything as it could be lost in transit.
For UDP you will never know if the data was received by the destination system unless you write a UDP-based protocol such that the remote system acknowledges the data.
For TCP the protocol stack will ensure that your code is notified if the data is lost in transit, but it may be many seconds before you receive confirmation.
I am currently writing a server for a fast paced multiplayer game, which should be run in UDP (I read TCP was inappropriate due to the way it handles packet drops, in applications requiring timely delivered data, please correct me if TCP is more useful) The game is not mass multiplayer, and should be hosted primarily by the players themselves, probably on local dedicated servers. While I am pretty sure that the client needs to be in NIO, to avoid game lag from network problems, I do not know how to write the server yet. Here is a list of possibilities I considered:
Using separate thread for each player with a socket bound to each
Using one single socket to loop through every player
Doing the same, but with NIO
using one socket to broadcast messages to all clients simultaneously
using one socket for receiving, and one for sending on a separate thread
Which of these is the most appropriate approach to handling time critical data with a relatively low number of clients? (no more than 16)
For 16 clients, unless your hardware sucks REALLY badly, or you do some outrageous processing, you'll be fine performance-wise either way you go. That means that you can write it any way it makes it simpler for you to write and maintain.
A few words about your options though:
Using separate thread for each player with a socket bound to each
This approach makes more sense for a low number of TCP sockets. If you're using UDP, you only have one socket, so there's no need for that. It is however useful to have a thread per client if your game requires some parallel processing per-client.
Using one single socket to loop through every player
This is probably the easiest option, unless your game requires really special. As I've said earlier, you should be fine performance-wise. So if it makes writing the code easier do it. Avoid premature optimizations.
using one socket for receiving, and one for sending on a separate
thread
Unless you have a good reason for doing this, I'd avoid this idea. It might (needlessly) complicate things network-wise since the clients will be sending packets to port X, and getting replies from port Y. NAT will be a serious issue.
using one socket to broadcast messages to all clients simultaneously
First of all, that would only work in one direction - from the server to the clients. Second, that would only work inside a LAN since routers don't forward broadcast packets. If you're fine with both limitations and find yourself designing a system in which the server sends some packets to all players (at least to those in the same network), that might not be a bad idea. As far as performance goes, unless you're sending a large number of packets, you'll probably won't notice a difference between sending each player a separate copy, and sending a broadcast.
TCP has more overheads, leading to higher bandwidth required to transmit the same information. TCP does however have the advantage of being resent if it doesn't arrive. Make sure the messages you send over the network are losable if you use UDP. for example, if you send movements as additions and alterations then it'll lose sync quickly with the clients. You'll need to overwrite values when transmitting.
You'll need a thread per player for listening to their outputs such as keystrokes or actions, as you have to wait for data on each thread and therefore it would block on player 1 until they make an action and player 2 would not be able to make action until player 1 had.
Broadcasting game states might make sense - but i have no experience with that or something as time critical as fast paced multiplayer games
An application level message is send over the network in a series of packets that are assembled in the receiving side and passed to the application level.
Is it possible in Java to do network programming in the level of these individual packets?
Or in Java we can only see the "application" level packet? I.e. the "big-packet" that is assembled by all these network packets?
I tried to research on google for this matter but the results where really confusing.
The confusion is due to the fact that some resources that are about UDP seem to indicate that the operation is on packets, while others say that Java can not work in raw sockets which implies that it works on a higher level of abstraction.I could not find an answer to exactly what I am looking for.
If yes, which package does this?
Is it possible in Java to do network programming in the level of these individual packets?
Yes, but it's very unlikely you would want individual packets.
Or in Java we can only see the "application" level packet?
Pure Java can only see TCP streams, and UDP datagram which have a one-to-one mapping with packets, but you have no access to the UDP header.
I.e. the "big-packet" that is assembled by all these network packets?
You don't get packets at all big or small. You read data and the data available is read (up to the size of your buffer)
If yes, which package does this?
You can use JPcap to see individual packets, however, this is rarely useful unless you need accurate time stamping of each packet or you need to trace dropped packets.
This uses winpcap (Windows) or libpcap (linux) via JNI.
In most of these cases where I have seen this used it was a lot of work for little gain.
from my point of view an answer mentioning JNI means that Java does not support it (since you have to actually code in another language for what you need)
Sockets, Files, GUI components all use JNI in the end. By this definition you can't do anything which uses a system call in Java, because the OS is not written in Java.
I don't think this is a useful definition of what you can do in Java.
1) Pure Java can only see TCP streams. What about UDP?
You don't have access to the packet's header with any protocol in Java without libPCap.
I assume this point means no packet access
Not without any additional libraries.
2) In most of these cases where I have seen this used it was a lot of work ? Why.
Because it is very low level and lots of details you don't normally have to worry about are exposed to you. Note: you might not get a packet as they can be dropped while attempting to record them and you won't be able to ask for them again so you miss them.
It is just a library right?
Correct.
Doesn't it work?
Why do you say that?
I am trying to see if what I need to do can be done in Java or should look into other languages.
IMHO, You won't find it any easier in another language.
I read in the jpcap docs that it can not reshape traffic e.g. drop packets etc. Why can't it do that?
You can't force a network to drop a packet and you can't trick the kernel in to drop one either. If you think about what a dropped packet is, the answer is fairly obvious.
You won't see packetized segments if some other device breaks your large UDP packet into smaller packets.
When reading TCP you'll read bytes as a stream. You'll have no idea how these bytes were actually sent. You could read back 100 bytes, and they could have been sent over 10 packets for all you know.
There's no way to access this information in java without JNI. Of course with JNI you can do anything :)
You seem to think that UDP == raw. It doesn't. Raw == IP, or even Ethernet. UDP is a layer over IP, as is TCP. You can't work in raw sockets in Java but you can work in UDP and TCP.
I need to implement a Peer To Peer File Transfer.
What protocol should I use? TCP or UDP? And why?
TCP is generically the best way to go when you want to ensure that your data gets to its intended destination with appropriate integrity.
In your case I would personnally choose tcp, because you will probably end up reimplementing tcp in some form inside of your udp packets otherwise (ask for block (syn), answer: i have block (syn ack), ok send it to me (ack)...data: (push ack)... ok done: (rst))
Also generically speaking, udp is the way to go when you want to broadcast, and you dont really care if the data gets there or not, meaning there is either high redundancy or low importance/integrity... since files require high integrity, it doesn't make a lot of sense to go UDP, again, unless you want to go through the extra work.
The only upside to udp would be the fact that is stateless, which could have some good implementations in a file sharing program.
Bottom line... go with your heart...
I'd recommend using TCP.
If you use UDP then you end up having to design and implement flow control and detection / retransmission of lost packets in your application-level protocol. Doing this in a way that gives you decent performance in good and bad networking conditions is hard work. For simple peer to peer, the payoff is generally not worth the effort.
FOLLOWUP
You ask:
and i plan to implement inter-lan calling over wifi, for that i would have to use UDP right?
Assuming that IP is implemented and the routing is set up correctly over your WiFi network(s), both UDP and TCP should work just fine.
UDP does not guarantee that the packets will be delivered, which is something that TCP does. Please take a look at this previous SO post which highlights the difference between these two protocols.
TCP helps ensure that your packets are received by the client and should be your choice for a file transfer because you want the file to be reproducible on the other end exactly as it is sent.
You can implement the file transfer using UDP too, but you would have to write your own logic for ensuring that the contents of the file are assembled correctly.
Since most users really care that all of their data makes it to the remote target with consistency, TCP is your best bet since packet error handling is managed. UDP is typically better for applications where loss is acceptable (e.g. player position in games) or where retransmission is not an option (e.g. streaming audio/video).
More on streaming
In the streaming A/V case, the data is always shipped with some error correction bits to fix some large percentage of errors. The endpoint manages the extra time required to detect (and potentially correct) the errors by buffering the stream. Nevertheless, it's obviously a ton of work (on both sides) to make it all happen and probably isn't worth it for P2P file transfer.
Update 1: audio streaming comment
The constraints are really based on required throughput, latency, and bit error rate (BER). Since these are likely both mobile devices, possibly operating across two carriers cellular networks, I'd opt for UDP with very high error-correction capability for audio. Users will likely be more displeased with no audio versus slightly corrupted audio and greater latency. Nevertheless, I would still use TCP for file transfer.
Please suggest java library, that implements reliable udp. It will be used for a game server to communicate to clients and to other servers.
PS Maybe you can suggest tech that will be more productive to work with for such task(game server)? But this must work on linux.
Edit: It's an action type game, so it needs to talk to server as fast as possible.
Edit 2: I found Enet which was used for a FPS game, but it's C++, will there be an overhead if I call it many times a second?
These are the libraries/frameworks I know of that implement something like reliable UDP:
Mobile Reliable UDP (MR-UDP)
MR-UDP aims at providing reliable communication based on UDP from/to mobile nodes (MNs), with least possible overhead. It extends a Reliable UDP (R-UDP) protocol with mobility-tolerating features, such as the ability to handle intermit-tent connectivity, Firewall/NAT traversal and robustness to switching of IP addresses or network interfaces (e.g. Cellular to WiFi, and vice-versa).
UDT-Java
Java implementation of UDP-based Data Transfer (UDT)
UDT is a reliable UDP based application level data transport protocol for distributed data intensive applications over wide area high-speed networks. UDT uses UDP to transfer bulk data with its own reliability control and congestion control mechanisms. The new protocol can transfer data at a much higher speed than TCP does. UDT is also a highly configurable framework that can accommodate various congestion control algorithms.
JNetRobust
Fast, reliable & non-intrusive message-oriented virtual network protocol for the JVM 1.6+.
It resides between the transport and the application layer.
Characteristics:
reliability of transmitted data
received, unvalidated data is available immediately
the package is bigger than UDP's package, but smaller than TCP's package
no flow control
no congestion control
Disclaimer: I'm the author of JNetRobust, it's new and still in alpha.
There is an java implementation of RUDP (Reliable UDP) protocol (RFC908, RFC1151)
http://sourceforge.net/projects/rudp/?source=dlp
You may find you don't need reliable messaging for all message types. For example, if you are repeatedly sending the status of things like players, and a few packets are lost it may not even matter.
There are reliable high performance UDP based libraries which support Java. One of these is 29West's LBM. It is not cheaper because it is very hard to get this right. Even with a professional product you may need a dedicated network for UDP to minimize loss.
For the purpose of a game I suggest you use a JMS service like ActiveMQ which runs wherever you can run Java. You should be able send 10K messages per second with a few milli-seconds latency.
When people say something must be as fast as possible, this can mean just about anything. For some people this means 10 ms, 1 ms, 100 us, 10 us, 1 us is acceptable. Some network routers support passing packets with a 600 ns latency. The lower the latency the greater the cost and the greater the impact on the design. Assuming you need more speed than you need can impact the design and cost unnecessarily.
You have to be realistic seeing that you have a human interface. A human cannot respond faster than about 1/20 of a second or about 50 ms. If you keep the messaging to less than 5 ms, a human will not be able to tell the difference.
Libjitsi has SCTP over UDP, which breaks everything up into packets like UDP but guarantees reliable delivery, like TCP. See https://github.com/jitsi/libjitsi/blob/master/src/org/jitsi/sctp4j/Sctp.java
UDP is by definition not a reliable service. It does not guarantee a high quality of service. You can, however, use TCP.