UDP file send data loss - java

I have the following codes. I have text file having about 500 kilobytes and I am sending this from client to server this way. Each line in the text file containt 64 letters so 64 bytes. After transfer completed, transferred file is about 150 kbs while my original file is about 500 kbs. Is it okey to send each line by converting to byte first? Also, line order changes in transferred file.
Client
private static DatagramSocket socket;
private static InetAddress address;
private static byte[] buf = new byte[64];
static Scanner file;
public static void main(String[] args) throws IOException{
socket = new DatagramSocket();
address = InetAddress.getByName("localhost");
file = new Scanner(new File("sentfile.txt"));
DatagramPacket packet;
while (file.hasNext()) {
String line = file.nextLine();
if (!line.isEmpty()) {
buf = line.getBytes();
packet = new DatagramPacket(buf, buf.length, address, 1100);
socket.send(packet);
}
}
file.close();
socket.close();
}
Server
private static DatagramSocket udpSocket;
private static byte[] buffer = new byte[64];
private static boolean running;
static PrintWriter writer;
public static void main(String[] args) throws IOException {
udpSocket = new DatagramSocket(1100);
running = true;
writer = new PrintWriter("receivedfile.txt");
DatagramPacket packet;
while(running) {
packet = new DatagramPacket(buffer, buffer.length);
udpSocket.receive(packet);
InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(buffer, buffer.length, address, port);
String received = new String(packet.getData(), 0, packet.getLength());
writer.write(received);
writer.write(System.getProperty("line.separator"));
if (received.equals("end")) {
running = false;
continue;
}
}
writer.close();
udpSocket.close();
}
I know there can be packet loss in udp but 3/2 is lost so I found it too much and wonder if it is because of my code not the nature of udp. Also udp code works slower than udp. Is there a such thing "TCP is faster for small sized data transfer"?

Related

send numbers in UDP socket in java

I am trying to send random numbers inside a UDP socket using this code below but the command sendData = number.getBytes(); is not working. Is it because I have to replace getBytes with something else?
public class UDPServer {
public void run() throws IOException {
DatagramSocket serverSocket = new DatagramSocket(5555);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while (true) {
DatagramPacket receivePacket =
new DatagramPacket(receiveData,
receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
Random dice = new Random();
int number;
for (int counter = 1; counter <= 10; counter++) {
number = dice.nextInt(6);
}
sendData = number.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
}
I take it you want to write the bytes of your ints in network byte order. Good. Java has a class for it: ByteBuffer.
Sample code, modify for your needs:
final ByteBuffer buf = ByteBuffer.allocate(8); // for 2 ints, an int is 4 bytes long
buf.putInt(4);
buf.putInt(3);
buf.rewind();
final DatagramPacket packet
= new DatagramPacket(buf.array(), buf.limit(), addr, port);
ByteBuffer does big endian by default, which is the network byte order. See its .order() method.

Java Socket UDP Loop

I am trying to set up a program that looks into UDP performance of packets and response times on my network. I have a client and server side class, for which I am specifying the packet size which to send pieces of text. For example, if I want to send a word of "Tester" in a 4 byte packet, it will send the "TEST" part but not reiterate through the rest of the word. I have tried to add in a while loop, but i don't think what I have is correct as it continuously sends the first 4 bytes. Does anyone know what sort of loop I need and where abouts it should be placed to get the outcome I am after? Code for the client is below. Many thanks in advance for any guidance.
//UDP Client
//Usage: java UDPClient [server addr] [server port]
import java.io.*;
import java.net.*;
public class UDPClient extends variable {
// static Integer portNo = 4444;
static Integer byteSize = 4;
public static void main(String[] args) throws Exception {
SocketForm form = new SocketForm();
long startTime; // Starting time of program, in milliseconds.
long endTime; // Time when computations are done, in milliseconds.
double time;
//get server address
String serverName = "localhost";
if (args.length >= 1)
serverName = args[0];
InetAddress serverIPAddress = InetAddress.getByName(serverName);
//get server port;
int serverPort = form.cliportNo;
if (args.length >= 2)
serverPort = Integer.parseInt(args[1]);
//create socket
DatagramSocket clientSocket = new DatagramSocket();
//get input from keybaord
byte[] sendData = new byte[byteSize];
BufferedReader inFromUser = new BufferedReader(new InputStreamReader (System.in));
while (true){ //incorrect as it is only repeating the first four bytes of the word typed in the console
String sentence = inFromUser.readLine();
startTime = System.currentTimeMillis();
sendData = sentence.getBytes();
//construct and send datagram;
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverIPAddress, serverPort);
clientSocket.send(sendPacket);
//receive datagram
byte[] receiveData = new byte [byteSize];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
//print output
String sentenceFromServer = new String(receivePacket.getData());
System.out.println("From Server:" + sentenceFromServer);
//close client socket
//clientSocket.close();
endTime = System.currentTimeMillis();
time = endTime - startTime;
//System.out.println("Time :" + time);
}
} //end of main
} //end of UDPClient
Do you mean like this?
private void sendChunked( String msg, int chunkSizeInBytes ) {
byte[] msgBytes = msg.getBytes();
for( int index = 0; index < msgBytes.length ; index += chunkSizeInBytes ) {
DatagramPacket packet = new DatagramPacket( msgBytes, index, Math.min( chunkSizeInBytes, msgBytes.length-index ));
send( packet ); // You know how that works ...
}
}

Clear Datagram Buffer in Java

So I got this simple udp client/server code from the internet, and it works. However, when I enter something that is shorter than the thing I entered before it, I get the remaining characters left over. For example, if I first enter:
kitty
And then enter:
cat
The second print reads as:
catty
I've been looking at other people with similar problems and most of them seem to be solved by clearing the byte array. However, if I try to implement their answers, it doesn't fix my problem. What do I need to do, and (maybe more importantly) where in the code should it go? Here is the code:
Client:
import java.io.*;
import java.net.*;
class UDPClient
{
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = inFromUser.readLine();
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 20700);
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
clientSocket.close();
}
}
Server:
import java.io.*;
import java.net.*;
import java.util.*;
class UDPServer
{
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(21200);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String( receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("RECEIVED: " + sentence);
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
}
}
}
You don't need to clear the byte array, but you do need to take some notice of the length of the DatagramPacket after the receive, via the getLength() method; for example:
new String(packet.getData(), packet.getOffset(), packet.getLength());
You're doing that correctly in the server, but not in the client.
You also need to reset the length before calling receive(). Otherwise the DatagramPacket will keep shrinking to the length of the smallest packet received so far.

UDP Client/Server object transfer help

I'm trying to transfer an ArrayList from a client to a server using the UDP protocol.
The transfer starts at the "max" if statement.
Same in the server side
This is the client:
public class UdpClient {
protected DatagramPacket sendPacket;
protected DatagramPacket receivePacket;
public static void main(String args[]) throws IOException,
ClassNotFoundException {
UdpClient upd = new UdpClient();
ArrayList<Integer> arr = new ArrayList<Integer>();
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(
System.in));
DatagramSocket clientSocket = new DatagramSocket();
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
ByteArrayOutputStream bStream = new ByteArrayOutputStream();
ObjectOutput oo = new ObjectOutputStream(bStream);
ByteArrayInputStream baos;
ObjectInputStream oos;
System.out
.println("Commands: Time, Date, Weather, Sum-number, Max-number, Exit");
while (true) {
String fromUsr = inFromUser.readLine();
if (fromUsr.equals("bye")) {
break;
} else if (fromUsr.equals("weather")) {
sendData = fromUsr.getBytes();
upd.sendPacket(sendData, clientSocket);
System.out
.println("Please select a ctiy: Lund, Malmo, Stockholm");
String weather = inFromUser.readLine();
sendData = weather.getBytes();
upd.sendPacket(sendData, clientSocket);
upd.receivePacket(clientSocket, receiveData);
} else if (fromUsr.equals("max")) {
sendData = fromUsr.getBytes();
upd.sendPacket(sendData, clientSocket);
String max = inFromUser.readLine().trim();
upd.nums(max, arr);
oo.writeObject(arr);
byte[] buf = new byte[bStream.toByteArray().length];
buf = bStream.toByteArray();
upd.sendPacket(buf, clientSocket);
System.out.println(arr);
} else {
// send data that of the user
sendData = fromUsr.getBytes();
upd.sendPacket(sendData, clientSocket);
upd.receivePacket(clientSocket, receiveData);
}
String fromServer = new String(upd.getData());
System.out.println("Message from server:\n" + fromServer);
}
}
private void sendPacket(byte[] sendData, DatagramSocket clientSocket)
throws IOException {
InetAddress IPAddress = InetAddress.getByName("ericman-PC");
sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress,
9876);
clientSocket.send(sendPacket);
}
private void receivePacket(DatagramSocket serverSocket, byte[] receiveData)
throws IOException {
byte[] rData = new byte[1024];
receiveData = rData;
receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
}
This is the Server
public class UdpServer {
protected DatagramPacket receivePacket;
protected DatagramPacket sendPacket;
public static void main(String args[]) throws IOException,
ClassNotFoundException {
UdpServer upd = new UdpServer();
DatagramSocket serverSocket = new DatagramSocket(9876);
DateFormat currentDate = new SimpleDateFormat("yyyy/MM/dd");
DateFormat currentTime = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
ByteArrayInputStream baos;
ObjectInputStream oos;
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
while (true) {
System.out.println("****************************************"
+ "\nServer is connected");
upd.receivePacket(serverSocket, receiveData);
String str = new String(upd.getData()).trim();
System.out.println("Message received is:" + " " + str);
if (str.equals("time")) {
str = currentTime.format(date);
sendData = str.getBytes();
upd.sendPacket(serverSocket, sendData);
} else if (str.equals("date")) {
str = currentDate.format(date);
sendData = str.getBytes();
upd.sendPacket(serverSocket, sendData);
} else if (str.equals("weather")) {
upd.receivePacket(serverSocket, receiveData);
str = upd.weather(str = new String(upd.getData()).trim());
sendData = str.getBytes();
upd.sendPacket(serverSocket, sendData);
} else if (str.equals("max")) {
byte[] buf = new byte[1024];
System.out.println("waitng for object to come");
upd.receivePacket(serverSocket, buf);
baos = new ByteArrayInputStream(buf);
oos = new ObjectInputStream(baos);
Object o = oos.readObject();
System.out.println(o);
} else {
str = "Unknown command, please try again..";
sendData = str.getBytes();
upd.sendPacket(serverSocket, sendData);
}
}
}
This is the error i get in the Server side
Exception in thread "main" java.io.StreamCorruptedException: invalid stream header: 00000000
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at UdpServer.main(UdpServer.java:54)
Line 54 that the error indicates is this line on the server
baos = new ByteArrayInputStream(buf);
oos = new ObjectInputStream(baos);
If you could help me out of why this error is happening? thanx!
Your code creates alot of arrays it immediately discards. I would use a debugger to step through the code so you understand what it is doing.
private void receivePacket(DatagramSocket serverSocket, byte[] receiveData)
throws IOException {
// create a new array
byte[] rData = new byte[1024];
// throw away the orignal array so the new array will be update.
receiveData = rData;
// copy into the new array, not the old one.
receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
}
In this case, the original receiveData will not me modified so it will contain lots of 0 bytes.
byte[] buf = new byte[bStream.toByteArray().length];
buf = bStream.toByteArray();
This creates three arrays when all you need is one. The first array bStream.toByteArray() is created just so you can determine what length it would be. You create a second array which is the same length but empty and put it in buf Finally you discard the second array and replace it with a copy of the first array.

UDP threading infinite loop in Java

I've written two programs. Now each program uses threading to send and receive packets at the same time.
Whenever I send packets from the server to the client, the message at the client ends gets received in an infinite loop. I.e; I've added a print statement that prints the message sent and this goes forever in an infinite loop. I want to make it so that it receives the message, and then be able to write back to the server and exit whenever the user wants to.
I've tried using socket.close(), but this makes it so that the client receives the message and I can only write back to the server once. After I send it, I can't send anymore. I want to make it so that I can write back more than once.
Can anyone please point me in the right direction?
My code is as follows;
public class UDPThreadClient extends Thread {
public static int port1;
//Create threaded server
UDPThreadClient (int port1) {
System.out.println ("Starting threaded client");
start();
}
public void run() {
int port = port1;
try {
DatagramSocket serverSocket = new DatagramSocket(port1);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while (true) {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String( receivePacket.getData());
SocketAddress address = receivePacket.getSocketAddress();
System.out.println("RECEIVED from " + address + " : " + sentence);
InetAddress IPAddress = receivePacket.getAddress();
//int port = receivePacket.getPort();
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
//serverSocket.close();
}
} catch (IOException e) {
System.out.println (e.getMessage());
}
}
//Create client
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
port1 = Integer.parseInt(args[1]);
new UDPThreadClient (port1);
try {
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = inFromUser.readLine();
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
//clientSocket.close();
} catch (IOException e) {
System.out.println (e.getMessage());
}
}
}
and
public class UDPThreadServer extends Thread {
public static int port1;
//Create threaded client
UDPThreadServer () {
System.out.println ("Starting threaded server");
start();
}
public void run() {
try {
DatagramSocket clientSocket = new DatagramSocket();
BufferedReader inFromUser = new BufferedReader (new InputStreamReader(System.in));
Scanner in = new Scanner (inFromUser);
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = new byte [1024];
byte[] receiveData = new byte [1024];
while (in.hasNextLine()) {
String sentence = in.nextLine();
//inFromUser.readLine();
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket (sendData, sendData.length, IPAddress, port1);
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket (receiveData, receiveData.length);
clientSocket.receive (receivePacket);
String modSentence = new String (receivePacket.getData());
System.out.println ("FROM SERVER: " + modSentence);
}
//clientSocket.close();
} catch (IOException e) {
System.out.println (e.getMessage());
}
}
//Create server
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
port1 = Integer.parseInt(args[1]);
new UDPThreadServer ();
try {
DatagramSocket serverSocket = new DatagramSocket (port);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while (true) {
DatagramPacket receivePacket = new DatagramPacket (receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
SocketAddress address = receivePacket.getSocketAddress();
System.out.println ("Received from " + address + " : " + sentence);
InetAddress IPAddress = receivePacket.getAddress();
String capSentence = sentence.toUpperCase();
sendData = capSentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket (sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
//serverSocket.close();
}
} catch (IOException e) {
System.out.println (e.getMessage());
}
}
}
Thanks.
Looking at UDPClientServer:
When you create the Datagram packet, you give it the port to send it to, not the port that you are sending it from.
When I ran your code, nothing happened. The server is waiting on port port, while the client sends to port port1. If you instead send to port port (not accessible from the main method, but changing it to a field instead of local method would fix that, then the infinite looping occurs because the server sends a packet to the same port it is listening on. There's your problem. Do you supply the same numbers as the first and second arguments to your program?
From the server, you can use receivePacket.getPort() to get the port where the packet came from.
EDIT:
Your two classes have much repetition, which is probably a source of confusion. One class has a main which starts a client then creates a server type loop tester. The other class sets up a Server then creates a client type tester.
Below is only the class you've named UDPThreadServer with comments showing changes to make the server 'work' with the testing code in the main method. Note that the server should send to a port that it is not listening to. You are also reading port values from command line arguments. I just made up some numbers for the ports and stuck them in as constants.
public class UDPThreadServer extends Thread
{
public static int port1;
UDPThreadServer()
{
//server or client? it's hard to say. you call the socket a clientSocket.
System.out.println("Starting threaded server");
start();
}
public void run()
{
try
{
// Here client(?) is set up with empty constructor.
// It is a mystery what port it will get.
DatagramSocket clientSocket = new DatagramSocket();
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
Scanner in = new Scanner(inFromUser);
InetAddress IPAddress = InetAddress.getByName("localhost");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
while (in.hasNextLine())
{
String sentence = in.nextLine();
// inFromUser.readLine();
sendData = sentence.getBytes();
// sending to port1? that must be the server.
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port1);
clientSocket.send(sendPacket);
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER: " + modSentence);
}
// clientSocket.close();
} catch (IOException e)
{
System.out.println(e.getMessage());
}
}
// Create server
public static void main(String[] args)
{
// int port = Integer.parseInt(args[0]);
int port = 1927; // or whatever
// port1 = Integer.parseInt(args[1]);
port1 = 1928;
new UDPThreadServer();
try
{
// server resides on port1? if client sends to port 1, then this is so.
DatagramSocket serverSocket = new DatagramSocket(port1);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
while (true)
{
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
SocketAddress address = receivePacket.getSocketAddress();
System.out.println("Received from " + address + " : " + sentence);
InetAddress IPAddress = receivePacket.getAddress();
String capSentence = sentence.toUpperCase();
sendData = capSentence.getBytes();
// where did you get the info from? Client is set up with an empty constructor, so it is a mystery.
port = receivePacket.getPort();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
// serverSocket.close();
}
} catch (IOException e)
{
System.out.println(e.getMessage());
}
}
}
Don't close the socket.
If that doesn't answer your question you need to clarify it.
while(true) is an infinite loop. Do you quit it in any case?

Categories