简体   繁体   English

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

[英]How to Send Files using UDP in Java

i have a project in socket programming using java.我有一个使用 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 :我知道 UDP 不是传输文件的好主意,但我必须将它作为一个项目来做我的代码是:

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.我在客户端第一眼看到的是,您尝试使用的dest字段永远不会被单元化,它仍然为空。 You should write dest = InetAddress.getByName(anArgument) so that the dest get a value of a new InetAddress instance.您应该编写dest = InetAddress.getByName(anArgument)以便dest获得新 InetAddress 实例的值。 So, most likely you'll get the Null pointer exception when your code gets compilable.因此,当您的代码可编译时,您很可能会收到 Null 指针异常。 Now it is not, as long as the neededpackets is not defined.现在是不是,只要neededpackets没有定义。

Here's a quick example I whipped up.这是我提出的一个快速示例。 It uses DatagramSocket connections, which I think are the only way of doing it.它使用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 );
   }
}

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.我创建了一个 UDP 库来使 UDP 类似于 TCP。 This is a much more reliable form of transferring within UDP.这是一种更可靠的 UDP 传输形式。

https://github.com/DrBrad/BetterUDPSocket 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这是在库中发送/接收文件的示例: 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.在我的库中,我使用 UUID 作为 ID,这是一个 16 字节的标识符,以确保数据包不会在流中混淆。 For example Lets say Alice wants to send 1.JPG as well as 2.JPG at the same time.例如,假设 Alice 想同时发送 1.JPG 和 2.JPG。 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 [0x00] DATA - 用于发送数据
  2. [0x01] SUCCESS ACK - Is for when the data is received notify the sender that we have received the data [0x01] SUCCESS ACK - 用于在收到数据时通知发送方我们已收到数据
  3. [0x02] FAIL ACK - The data is out of order, this will make the sender send the last packet [0x02] FAIL ACK - 数据乱序,这将使发送方发送最后一个数据包
  4. [0x03] KEEP ALIVE - Send a small packet every 25 seconds to keep your NAT from closing the port [0x03] KEEP ALIVE - 每 25 秒发送一个小数据包,以防止 NAT 关闭端口
  5. [0x05] CLOSE - Tells the client/server that we have closed the connection [0x05] CLOSE - 告诉客户端/服务器我们已经关闭了连接

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.最后对于 ORDER 我们必须确保在发送文件时所有数据都是有序的,很可能在处理数据时接收方可能没有得到最后一个数据包。 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.为了解决这个问题,我们让客户端和服务器对成功发送/接收的每个数据包进行计数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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