这个怎么做?第一次做类似的题,求各位大神帮助下。代码最好了。。急急急。

解决方案 »

  1.   

    问题补充:
    1、为了UDP包不在IP层上被分片,所以设计UDP包每个不得大于以太网的MTU,综合考虑,包大小不超过512字节(不包括UDP头部)。2、使用java nio实现。3、设计一个应用层协议Head,使得支持重发,可以不考虑分片,即限制应用层协议数据包大小不会超过512字节即可。可参考TCP或者IP的重发机制。
      

  2.   

    如果是纯UDP协议,那就这样:
    * 消息头部包含一个序列号(sequence number),客户端检测该序列号来判断是否有丢包
    * 客户端检测到有丢包,那一定是收到了包p,以及包p+k,且k>1。那如何通知服务器端丢包呢?就只能发一个重传请求,而客户端同时应该开始队列从服务器端收到的包
    * 服务器收到了客户的重发请求,开始发送p+1到p+k-1的包
    * 客户端开始处理重发的包,如果在这中间仍然发现了丢包,那就继续发送重传请求,并队列发现丢包现象之后的重传包
       > 注意这里的队列以及前面所说的是优先队列,按序列号排序,可以简化算法
    * 服务器端如果在完成重传之前又收到了重传请求,则应该队列该请求,在完成重传之后继续
    * 在客户端发送重传请求之后,如果服务器端没有在一定时间内回复,则判定该请求丢包,继续重传该请求UDP就是这么麻烦,慢慢享受吧
      

  3.   

    这是我在课余没事的时候写的一个东西,不知道是否正确,但基本上应该可以完成相应的功能。支持文件和文件夹的传输,不过这里的包大小为10000字节。我想改一下应该可以
    服务器package fileTransport;import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.SocketTimeoutException;
    import java.net.UnknownHostException;public class SentFile { /**
     * @param args
     */
    private InetAddress ip = null;
    private int port = 0; 
    private DatagramSocket socket ;
    private InetAddress toIp = null;
    private int toPort = 0;
    public static void main(String[] args) throws UnknownHostException {
    SentFile s = new SentFile(InetAddress.getLocalHost(),11111);
    File file = new File("g:\\download");
    s.sentFile(file);
    }
    public SentFile(InetAddress ip ,int port){
    this.ip = ip ; 
    this.port = port; 
    try {
    socket = new DatagramSocket(port , ip);
    } catch (SocketException e) {
    e.printStackTrace();
    }

    }
    public int sentFile(final File file){
    Thread th = new Thread(){
    public void run(){
    byte[] b = new byte[1000];
    DatagramPacket p = new DatagramPacket(b,b.length);
    try {
    socket.receive(p);
    byte[] date = p.getData();
    System.out.println(new String(date));
    } catch (IOException e) {
    e.printStackTrace();
    }
    toIp = p.getAddress();
    toPort = p.getPort();
    send(file,"");
    byte[] over = "over".getBytes();
    DatagramPacket p1 = new DatagramPacket(over,over.length);
    p1.setAddress(toIp);
    p1.setPort(toPort);
    try {
    socket.send(p1);
    } catch (IOException e) {
    e.printStackTrace();
    }

    }

    };
    th.start();

    return 1;
    }
    private void send(File file,String name){
    String name1 = name+"\\"+file.getName();
    if(file.isDirectory()){

    String s = "path"+name1;

    byte[] b = s.getBytes();
    DatagramPacket p = new DatagramPacket(b,b.length);
    p.setAddress(toIp);
    p.setPort(toPort);
    try {
    socket.send(p);
    } catch (IOException e) {
    e.printStackTrace();
    }
    try {
    System.out.println("recieve");
    socket.receive(p);
    System.out.println("recieved");
    } catch (IOException e) {
    e.printStackTrace();
    }
    for(int i = 0 ; i<file.listFiles().length; i++){
    send(file.listFiles()[i],name1);
    }
    }
    else{
    String s = "file"+name1+"length"+file.length();

    byte[] b = s.getBytes();
    DatagramPacket p = new DatagramPacket(b,b.length);
    p.setAddress(toIp);
    p.setPort(toPort);
    try {
    socket.send(p);
    } catch (IOException e) {
    e.printStackTrace();
    }
    try {
    socket.receive(p);
    } catch (IOException e) {
    e.printStackTrace();
    }
    byte[] buffer = new byte[10000];
    byte[] sendbuffer = new byte[10001];
    DatagramPacket pk = new DatagramPacket(sendbuffer,10001);
    pk.setAddress(toIp);
    pk.setPort(toPort);
    long sum = 0; 
    FileInputStream fis = null;
    BufferedInputStream bis = null;
    try {
    fis = new FileInputStream(file);
    bis = new BufferedInputStream(fis);
    bis.(10000);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    }
    int read = 0;
    int num= 0;
    try {
    socket.setSoTimeout(3000);
    boolean re = false;
    while(-1!=(read=bis.read(buffer))){
    sum+=read;
    System.arraycopy(buffer, 0, sendbuffer, 0, read);
    sendbuffer[10000] = Integer.valueOf(num).byteValue();
    pk.setData(sendbuffer);
    socket.send(pk);
    System.out.println(sum);
    while(!re){
    try{
    socket.receive(p);
    re = true;
    }catch(SocketTimeoutException timeout){
    socket.send(pk);
    }
    }
    re = false;


    Integer bn = new Integer(p.getData()[0]);
    System.out.println(bn+","+num+","+read);

    if(bn==-1){

    break;

    }
    if(bn!=(num+1)%100){
    bis.reset();
    }
    else{
    bis.(10000);
    num++;
    num%=100;
    }
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    try {
    bis.close();
    fis.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
      

  4.   

    客户端:
    package fileTransport;import java.awt.FileDialog;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FilenameFilter;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.util.ArrayList;import javax.swing.JButton;
    import javax.swing.JFileChooser;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.UIManager;public class GetFile { /**
     * @param args
     * @throws UnknownHostException 
     */
    public static void main(String[] args) throws UnknownHostException {
    GetFile g;
    try {
    g = new GetFile(InetAddress.getLocalHost(),11111,"download");
    g.getFile();
    } catch (UnknownHostException e1) {

    e1.printStackTrace();
    }

    }
    private DatagramSocket socket = null;
    private String name="";
    private InetAddress ip = null;
    private int port = 0 ; 
    private String saveName=null;
    public GetFile(InetAddress ip ,int port,String name){
    this.ip = ip ; 
    this.port = port ; 
    this.name = name;
    try {
    this.socket = new DatagramSocket();
    } catch (SocketException e) {
    e.printStackTrace();
    }

    }
    public String chooseSavePath(){
    try {
    if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1){
    UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    }
    } catch (Exception e1) {
    System.out.println("设置界面感官异常!");
    e1.printStackTrace();
    }
    JFileChooser fileChooser = new JFileChooser();
    fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
    fileChooser.setSelectedFile(new File(name));
    int i = fileChooser.showSaveDialog(null);
    System.out.println(i);
    if(i == JFileChooser.APPROVE_OPTION){
    if(fileChooser.getSelectedFile().exists()){
    JOptionPane.showConfirmDialog(null, "文件已存在,请重新命名");
    return chooseSavePath();
    }
    return fileChooser.getSelectedFile().getAbsolutePath();


    }
    return null;
    }
    public void getFile(){
    String path = chooseSavePath();
    System.out.println(path);
    if(path!=null){
    byte[] b = "ok".getBytes();
    DatagramPacket p = new DatagramPacket(b,b.length);
    p.setPort(port);
    p.setAddress(ip);
    try {
    socket.send(p);
    } catch (IOException e) {
    e.printStackTrace();
    }
    boolean end = false;
    while(!end){
    byte[] data = new byte[1024];
    DatagramPacket p1 = new DatagramPacket(data,data.length);
    try {
    socket.receive(p1);
    } catch (IOException e) {
    e.printStackTrace();
    }
    String msg = new String(p1.getData()).trim();
    System.out.println(msg);
    if(msg.equals("over")){
    end = true;
    System.out.println(end);
    }
    else{

    String type = msg.substring(0, 4);

    String newName = path+msg.substring(msg.indexOf(name)+name.length());
    if(type.equals("path")){
    File fpath = new File(newName);
    if(fpath.exists()){
    JOptionPane jop = new JOptionPane();
    JButton[] options = new JButton[3];
    options[0]= new JButton("覆盖");
    options[1] = new JButton("保存为:"+this.saveName+"(new)");
    options[2] = new JButton("取消");
    jop.setOptions(options);
    jop.setVisible(true);
    }
    else{
    fpath.mkdirs();
    }
    byte[] reb = "path".getBytes();
    DatagramPacket respons = new DatagramPacket(reb,reb.length);
    respons.setAddress(ip);
    respons.setPort(port);
    try {
    socket.send(respons);
    } catch (IOException e) {

    e.printStackTrace();
    }
    }
    else if(type.equals("file")){

    File file = new File(newName.substring(0, newName.indexOf("length")));
    FileOutputStream fos = null;
    try {
    fos = new FileOutputStream(file);
    } catch (FileNotFoundException e1) {

    e1.printStackTrace();
    }
    byte[] reb = "file".getBytes();
    DatagramPacket respons = new DatagramPacket(reb,reb.length);
    respons.setAddress(ip);
    respons.setPort(port);
    try {
    socket.send(respons);
    } catch (IOException e) {

    e.printStackTrace();
    }
    String s1=newName.replaceAll(".*[^\\d](?=(\\d+))","");
    long size = Long.valueOf(s1);
    long sum = 0;
    byte[] buffer = new byte[10001];
    DatagramPacket pk = new DatagramPacket(buffer,10001);
    int k = 0 ; 
    byte[] bn = new byte[1];
    for(long j = 0 ; j<size/10000 ; j++){
    try {
    sum+=10000;
    socket.receive(pk);
    Integer num = new Integer(buffer[10000]);
    if(num==k){
    fos.write(buffer, 0, 10000);
    fos.flush();

    if(j!=size/10000-1){
    k++;
    k%=100;
    bn[0] = Integer.valueOf(k).byteValue();
    System.out.println(bn[0]);
    respons.setData(bn);
    socket.send(respons);
    }
    else{
    if(size%10000==0){
    bn[0] = Integer.valueOf(-1).byteValue();
    System.out.println(bn[0]);
    respons.setData(bn);
    socket.send(respons);
    }
    }
    }
    else{

    bn[0] = Integer.valueOf(k).byteValue();
    System.out.println(bn[0]);
    respons.setData(bn);
    socket.send(respons);
    j--;
    }

    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    if(size%10000!=0){
    if(size>10000){
    k++;
    k%=100;
    bn[0] = Integer.valueOf(k).byteValue();
    System.out.println(bn[0]);
    respons.setData(bn);
    try {
    socket.send(respons);
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    }
    try {
    socket.receive(pk);
    bn[0] = Integer.valueOf(-1).byteValue();
    respons.setData(bn);
    socket.send(respons);
    } catch (IOException e) {
    e.printStackTrace();
    }
    try {
    fos.write(buffer, 0, (int)(size%10000));
    fos.flush();

    } catch (IOException e) {
    e.printStackTrace();
    }

    }
    try {
    fos.flush();
    fos.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    else{
    System.out.println("文件传输失败");
    socket.close();
    System.exit(0);
    }
    }
    }
    }
    else{
    return;
    }
    }
    }
      

  5.   

    这个代码不是我要的,你用的是io,我需要的nio写的!!!
      

  6.   

    既然如此。。给你一个简易的开头吧。。
    下面的代码每隔一秒发送一个int到ChannelReader类,由它打印出。至于buffer为什么要这么多操作,仔细看API文档吧
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.DatagramChannel;public class UDPDemo {
      public static void main(final String[] s) throws IOException, InterruptedException {    new Thread(new ChannelReader()).start();    DatagramChannel channel = DatagramChannel.open();
        channel.connect(new InetSocketAddress("localhost", 9999));    ByteBuffer buffer = ByteBuffer.allocate(50);
        int i = 0;
        while (true) {
          buffer.putInt(i++);
          buffer.flip();
          channel.write(buffer);
          buffer.clear();
          Thread.sleep(1000);
        }
      }  private static class ChannelReader implements Runnable {
        @Override
        public void run() {
          try {
            DatagramChannel channel = DatagramChannel.open();
            channel.bind(new InetSocketAddress("localhost", 9999));
            ByteBuffer buffer = ByteBuffer.allocate(50);
            while (true) {
              channel.receive(buffer);
              System.out.println(buffer.getInt(0));
              buffer.clear();
            }
          }
          catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
      

  7.   

    我弄明白了你的这个demo,bufer的这些操作也明白了,先谢谢你。另外,我想问的是设计一个UDP传输协议,这个怎么体现出来?
      

  8.   

    传输协议要你自己设计。所谓协议就是客户端和服务器端都认同的消息格式。
    UDPDemo中包含了一个简易协议,那就是每个包开头都是一个int
    所以你如果要实现更复杂的功能,就要定义更复杂的协议在我这个例子里,每个包开头的int是逐个递增的。如果你想检测到丢包,那就在客户端写一个逻辑,来判断收到的这个包的这个int,是不是之前那个包的int值+1至于重发,也就是你检测到丢包的时候,客户端要告诉服务器它丢包了,也是通过发送一个UDP包到服务器,然后服务器收到这个包之后开始回传丢失的那些包。代码其实可以从这个Demo改,只不过现在客户端和服务器端都要包含一个Reader一个Sender了
      

  9.   

    不是。协议是一种约定,让接受方能正确解码发送方的数据。当你面对一堆字节的时候,怎样把它还原成原来的消息,这就是协议规定的内容。比如说,前四个字节是一个int