简体   繁体   中英

How to Send Files using UDP in Java

i have a project in socket programming using java. We must write the Client and server Codes to transmit a file , The code shows no error at compiling but doesn't execute , it freezes when i put the name of the file .

I know that UDP is not a good idea for transmitting files but i have to do it as a project My codes are :

Client Code

import java.io.*;
import java.net.*;
import java.util.*;
public class Client
{
static InetAddress dest;
public static void main(String [] args) throws Exception
{

    DatagramSocket clskt = new DatagramSocket();
    Scanner input = new Scanner (System.in);
    int port =input.nextInt();
    System.out.println("Enter Destination Host name");
    String hostname=input.next();
    dest.getByName(hostname);
    int packetcount=0;
    System.out.println("Enter The path of the file you want to send");
    String path = input.next(); 
    File initialFile = new File(path);
            FileInputStream targetStream = new FileInputStream(initialFile);
    int filesize=targetStream.available();
    //int neededpackets =(int)Math.ceil((double)(size/1024));
     byte [] data= new byte[1024];
     // counting bytes
     for (int i=0;i<1024;i++)
     {
         data[i]=(byte)targetStream.read();
     }
     //create a packet
    DatagramPacket clpkt=new DatagramPacket(data,data.length,dest,port);
    packetcount++;
    clskt.send(clpkt);
    if(packetcount >neededpackets)
        clskt.close();
   }

 }

Server Code

 import java.io.*;
 import java.net.*;
 import java.util.*;

 class Server1
   {
public static void main(String args[])throws Exception
{
    System.out.println("Enter Port number !!!");
    Scanner input = new Scanner(System.in);
    int SPort = input.nextInt();
    DatagramSocket srvskt = new DatagramSocket(SPort);
    byte[] data =new byte[1024];
    System.out.println("Enter a full file name to save data to it ?");
    String path = input.next();
    System.out.println("file : "+path+" will be created.");
    FileOutputStream  FOS = new FileOutputStream(path);
    DatagramPacket srvpkt = new DatagramPacket(data,1024);
    System.out.println("listening to Port: "+SPort);
    int Packetcounter=0;//packet counter
    while(true)
       {
           srvskt.receive(srvpkt);
           Packetcounter++;
           String words = new String(srvpkt.getData());
           InetAddress ip= srvpkt.getAddress();
           int port = srvpkt.getPort();
           System.out.println("Packet # :"+Packetcounter+"
            Received from Host / Port: "+ip+" / "+port);
           FOS.write(data);
           //out16.flush();
           if (Packetcounter >=100)
                 break;

      }
    FOS.close();//releasing file.
    System.out.println("Data has been written to the file !");
  }
}

Thanks in advance for all.

What I see at the first glance in the client is that the dest field that you try to use gets never unitialized, it remains null. You should write dest = InetAddress.getByName(anArgument) so that the dest get a value of a new InetAddress instance. So, most likely you'll get the Null pointer exception when your code gets compilable. Now it is not, as long as the neededpackets is not defined.

Here's a quick example I whipped up. It uses DatagramSocket connections, which I think are the only way of doing it.

public class BroadcastTest
{
   private static final int RANDOM_PORT = 4444;

   public static void main( String[] args )
           throws Exception
   {
      InetAddress addr = InetAddress.getByName( "127.0.0.1" );
      DatagramSocket dsock = new DatagramSocket();
      byte[] send = "Hello World".getBytes( "UTF-8" );
      DatagramPacket data = new DatagramPacket( send, send.length, addr, RANDOM_PORT );
      dsock.send( data );
   }
}

Here's the server code. These seem to work but I have not thoroughly tested them!

class Server {
   private static final int RANDOM_PORT = 4444;

   public static void main(String[] args) {
      try {
         DatagramSocket dsock = new DatagramSocket( RANDOM_PORT );
         DatagramPacket data = new DatagramPacket( new byte[ 64*1024 ], 64*1024 );
         dsock.receive( data );
         System.out.println( new String( data.getData(), 0, 
                 data.getLength(), "UTF-8" ) );
      } catch( SocketException ex ) {
         Logger.getLogger(Server.class.getName() ).
                 log( Level.SEVERE, null, ex );
      } catch( IOException ex ) {
         Logger.getLogger(Server.class.getName() ).
                 log( Level.SEVERE, null, ex );
      }
   }
}

Hopefully this helps you or someone in the future. I have created a UDP library to make UDP similar to TCP. This is a much more reliable form of transferring within UDP.

https://github.com/DrBrad/BetterUDPSocket

Heres an example for sending/receiving files within the library: https://github.com/DrBrad/BetterUDPSocket/blob/main/src/unet/uncentralized/betterudpsocket/Samples/FileTransfer.java

The way this can be achieved is by creating a new protocol. For example

+----+------+-------+------+
| ID | CODE | ORDER | DATA |
+----+------+-------+------+

In my library I used a UUID for the ID, this is a 16 byte identifier to ensure that packets don't get mixed up in streams. For example Lets say Alice wants to send 1.JPG as well as 2.JPG at the same time. We can't mix up these packets.

I created a few CODE's that may be helpful:

  1. [0x00] DATA - Is for sending the data
  2. [0x01] SUCCESS ACK - Is for when the data is received notify the sender that we have received the data
  3. [0x02] FAIL ACK - The data is out of order, this will make the sender send the last packet
  4. [0x03] KEEP ALIVE - Send a small packet every 25 seconds to keep your NAT from closing the port
  5. [0x05] CLOSE - Tells the client/server that we have closed the connection

Finally for the ORDER We have to make sure when sending a file that all the data is in order, It is very possible that when processing data the receiver may not get the last packet. This can cause the packets to be out of order. To counter this we have the client and the server count each packet sent/received successfully.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM