如何使用Java中的UDP发送文件

时间:2015-10-26 18:19:27

标签: java sockets udp

我在使用java进行套接字编程时有一个项目。我们必须编写客户端和服务器代码来传输文件,代码在编译时没有显示错误但是没有执行,当我输入文件名时它会冻结。

我知道UDP对于传输文件不是一个好主意,但我必须将其作为项目进行我的代码是:

客户代码

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();
   }

 }

服务器代码

 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 !");
  }
}

提前感谢所有人。

3 个答案:

答案 0 :(得分:0)

我在客户端第一眼看到的是,您尝试使用的dest字段从未被酉化,它仍为空。您应该编写dest = InetAddress.getByName(anArgument)以便dest获取新InetAddress实例的值。因此,当代码可编译时,很可能会得到Null指针异常。现在它不是,只要没有定义neededpackets

答案 1 :(得分:-1)

这是我掀起的一个简单例子。它使用DatagramSocket个连接,我认为这是唯一的方法。

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 );
   }
}

这是服务器代码。这些似乎有用,但我还没有彻底测试过它们!

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 );
      }
   }
}

答案 2 :(得分:-1)

希望这对您或将来的某人有所帮助。我创建了一个 UDP 库来使 UDP 类似于 TCP。这是一种更可靠的 UDP 传输形式。

https://github.com/DrBrad/BetterUDPSocket

以下是在库中发送/接收文件的示例:https://github.com/DrBrad/BetterUDPSocket/blob/main/src/unet/uncentralized/betterudpsocket/Samples/FileTransfer.java

实现这一点的方法是创建一个新协议。例如

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

在我的库中,我使用 UUID 作为 ID,这是一个 16 字节的标识符,以确保数据包不会在流中混淆。例如,假设 Alice 想同时发送 1.JPG 和 2.JPG。我们不能混淆这些数据包。

我创建了一些可能有用的代码:

  1. [0x00] DATA - 用于发送数据
  2. [0x01] SUCCESS ACK - 用于在收到数据时通知发送方我们已收到数据
  3. [0x02] FAIL ACK - 数据乱序,这将使发送方发送最后一个数据包
  4. [0x03] KEEP ALIVE - 每 25 秒发送一个小数据包,以防止 NAT 关闭端口
  5. [0x05] CLOSE - 告诉客户端/服务器我们已经关闭了连接

最后为了订单 我们必须确保在发送文件时所有数据都是有序的,很可能在处理数据时接收方可能没有得到最后一个数据包。这可能会导致数据包乱序。为了解决这个问题,我们让客户端和服务器对成功发送/接收的每个数据包进行计数。