Java UDP packet sending and receiving issue - java

I'm working on a project for class using Java and UDP senders and receivers. The premise of the problem is to read in a text file, store the contents within a packet, send the packet, receive the packet, and read out the file on screen and create a new text document on the receiving computer of an identical text file.
I have all of that working. When I test with a local host it appears to work 100% of the time. When I send it from my laptop to my PC it appears to work 100% of the time. However, when I send it from my PC to my laptop it does not work.
I have several System.out debug statements to verify some of the information I send. I know that the text file should take 7 packets. However, whenever I send it from my PC to my laptop it says that I am sending 46 packets.
My initial thought is that maybe the packets are being sent out of order. The first packet I am sending indicates how many packets the receiver should be expecting to receive. I thought maybe for some reason the "46" could indicate a capital "F" so I removed all the capital "F" and it still says I'm sending 46 packets.
I thought maybe I was sending too much information at once so I used Thread.sleep() to give my receiver time to keep up -- that did not work either.
Finally, I read through the Oracle Documentation and some posts online and found out that UDP is unreliable. So, I'm assuming it could potentially be that. However, I want to just verify that that could be the issue.
Or if anyone has a better idea as to what could be causing the problem that would be awesome as well!
Thanks for your help :)

Yes, UDP is an unreliable protocol. UDP messages may be lost, and neither the sender or receiver will get any notification.
The 7 packets becomes 46 packets is typically due to fragmentation at the IP packet level. The protocol level beneath IP (e.g. physical ethernet packets, wifi packets etc) typically has a hard limit on the largest IP packet that can be sent "in one go", and similar limits are imposed by network routers, gateways and so on. If an IP packet that is larger than the limit is sent, two things can happen:
The IP packet may turned into "fragments" that need to be reassembled by the receiver.
The intermediate equipment can sent an ICMP message back to the sender telling it to send smaller IP packets.
In either case, the net result is that the number of IP packets needed to send a given sized UDP message can vary, depending on the network.
Of course, if a UDP message needs to be sent as multiple IP packets, AND there is local congestion in the network, that will increase the likelihood of packets, and hence messages failing.
But the bottom line is that UDP is not reliable. If you want reliability, the simple solution is to use TCP instead.

Related

Java: Is corrupt data possible with UDP in Java

I am writing a network test, which sends UDP packets with different sizes (up to 50k bytes). I want to measure ping and package loss. Do I also have to check the data transferred, or is the package dropped if it contains corrupt data?
First of all, the TCP/IP protocol suite (which includes UDP) is implemented in all modern operating systems. The implementation is often referred to as the network stack. The Java virtual machine itself uses regular user-level sockets for its networking, so it uses the operating system's network stack. All you can do from Java is set socket options, specify the source and destination, and provide the data to be sent. So I wouldn't worry about creating malformed packets from Java. The segment (layer 4), packet (layer 3) and frame (layer 2) are all created for your application by the OS. Nothing you can do with regular sockets can change that unless you're using raw sockets.
Second, there are multiple error detection codes in each TCP/IP packet. UDP and TCP have a 16 bit checksum code that verifies the header, the packet's payload, and several IP header field. IP packets themselves have a header checksum, and both Ethernet (802.3) and Wifi (802.11) have their own error detection mechanisms at the frame level. The default behavior I've seen in both networking equipment and endpoint operating systems when handling erroneous packets, is dropping them. So there's really very little chance of getting errors in your user-level socket.
Edit:
One point worth mentioning about UDP is that unlike the stream-oriented TCP, UDP sockets operate on a per-packet basis. So whatever you send() using a UDP socket, will be sent as a single UDP packet. I'd suggest making sure you don't put anything too big in there at any single point. Don't try to send a big 4KiB chunk as a single packet, because that will cause IP-level fragmentation. Do your best to make sure the packets being sent are at least 20 bytes smaller than the smallest MTU along the path from your machine to your destination (20 bytes is because the IP header is normally 20 bytes long). When in doubt, limit the data sent per packet to about 1000-1200 bytes, well below the common ~1400-1500 MTU limit.

What is better for instant messenger TCP or UDP?

I need to implement client/server instant messenger using pure sockets in Java lang.
The server should serve large number of clients and I need to decide which sockets should I use - TCP or UDP.
Thanks, Costa.
TCP
Reason:
TCP: "There is absolute guarantee that the data transferred remains intact and arrives in the same order in which it was sent."
UDP: "There is no guarantee that the messages or packets sent would reach at all."
Learn more at: http://www.diffen.com/difference/TCP_vs_UDP
Would you want your chat message possibly lost?
Edit: I missed the part about "large chat program". I think because of the nature of the chat program it needs to be a TCP server, I cannot imagine the actual text content sent by users over a UDP protocol.
The max limit for TCP servers is 65536 connections at the same time. If you really need to go past that number you could create a dispatcher server that would send incoming connects to the appropriate server depending on current server loads.
You could use both. Use TCP for exchanging the actual messages, (so no data lost and streaming large messages, (eg. containing jpegs etc), is possible. Use UDP only for sending short 'connectNow' messages to clients for which there are messages queued. The clients could have states like (NotLoggedIn, TCPconnected, TCPdisconnected, LoggedOut) with various timeouts to control the state transitions as well as the normal message-exchange events. The UDP 'connectNow' message would instruct clients in 'TCPdisconnected' to connect and so move to 'TCPconnected', where they would stay, exchanging messages, until some inactivity timer instructs the client to disconnect for now. This would, of course, be unreliable and so you may wish to repeat the 'connectNow' message every X seconds for N times until the client connects. The client should, in any case, attempt a poll every X minutes, just in case...
It depends whether the user needs to know if the messages have been delivered to the server. UDP packets have no inherent acknowledgement. If the client sends an IM message to the server and it gets lost in transit, neither the client or the server will know about it.
(The short answer is "use TCP" ... but it is worth thinking through the design implications for yourself.)
TCP would give you reliability, which is certainly desirable when during instant messaging -- you would not want messages to be dropped during converstation.
However, if you intend on using group messaging, then you might end up using mulitcast. For such cases, UDP would be the right chioce since UDP can handle point to multipoint. Using TCP for multicast applications would be hard since now the sender would have to keep track of retransmissions/sending rate for multiple receivers. One alternative could be to use TCP for point-to-point chat and use UDP for group messaging.

Measuring packet loss with Java

I'm developing an app that analyses the quality of your internet connection, and part of that is measuring packet loss.
I was thinking of sending packages to an IP address, but how can I send messages and check that they return? I'm guessing I need to send a package prompting a reply, but I can't find an example of that using either search or Google.
Or should I use existing traffic(how?)?
Besides that, how do I measure round trip time?
As TCP is reliable transport, you don't see dropped packets. In Linux you can use ifconfig to see how many retransmits you incurred. I am not sure what command line tools would show you this on Android, but you would need to use a system tools to give you this information.
BTW You can estimate the packet loss using UDP packets.The packets loss rate for UDP and TCP is not the same but it gives you an idea.
You'll need to use UDP, or ICMP (ping) for this as you won't be able to see TCP packet loss easily.
If you use ICMP you'll need to ensure the opposite computer responds to ICMP. Firewalls often block ICMP.
If you use UDP the other computer will need server software which can recognize your packets and reply as quickly as possible. The simpliest type of server for this would be called an Echo Server.
Here's a Java UDP Echo Server
Round trip time can be measured by taking the difference between the time you transmit a packet to the time you receive a reply for that transmission. Your protocol should be trivial so as not to pollute roundtrip time with processing time.

Only 16 UDP 512 byte packets being received by server when I sent 7mb total

I break a 7mb file into 512b chunks and I send it with udp to a server. About 14000 packets get sent by the client but on the server side socket.receive(packet) blocks after receiving only 16 packets.
Any ideas what's going on here?
UDP is defined as an unreliable protocol. Packets may be lost, and without the sender being informed. They may also arrive out of order and even duplicates may arrive.
UDP is suitable for purposes where error checking and correction is either unnecessary, or is performed by the application itself.
If you want a reliable protocol, start using TCP.
In contrast to TCP, UDP does neither ensure packet order nor actual delivery (no flow control as in TCP). See this question: ensuring packet order in UDP

no-blocking server and thread safe

I have a server which use one thread to receive UDP DatagramPackets from a remote data source; and a TCP ServerSocket to listen to remote clients request and spawn a dedicated thread for each client.
I want to transfer each DatagramPackets through the ServerSocket to the multiple clients. And now i encountered significant packet loss. Could anybody give some advice?
Thanks in advance。
Can it be just wrong choice of protocols in design ?
Something supposed to be reliable for multiple clients, as you use TCP. But reliability failed because of introduced dependency on UDP trough coupling (bridging/rebroadcasting) on server side.
UDP is more or less applicable for reliable applications, if you take into account that packets will be lost by design.
Solution 1: change protocol
Solution 2: if not possible to change protocol, then change expectations of user on client side about quality of service
Solution 3: add redundancy to UDP side to repeat requests, stock data ahead of time expecting future drops of quality, maintain large accumulated cache of data to feed clients no matter what.
It would be more to the point to get rid of UDP at the sender rather than try to shoehorn it somehow into your TCP design at the receiver, where it is already too late. The packets are lost between the sender and receiver, not in your receiver. Fixing the receiver code won't fix the actual problem.
Without knowing anything about your application design, I can make the following guesses:
Your UDP source is sending more packets than your receiver can handle causing packets to be dropped, because
your receiver is being blocked when passing off the packets to the TCP clients, because
your TCP clients are not picking up the packets quickly enough causing the buffer to fill up (which forces the server to block which causes it to miss UDP packets).

Categories