设计一个基于UDP的传输协议,能够实现丢包后重发,并使用java nio实现他.

打酱油的小酱油 2013-05-02 07:43:57
这个怎么做?第一次做类似的题,求各位大神帮助下。代码最好了。。急急急。。。。
...全文
830 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
这个协议怎么做呢。。。
  • 打赏
  • 举报
回复
不会呀。。。。
Inhibitory 2013-05-06
  • 打赏
  • 举报
回复
做过模拟网络发送数据,多个服务器互联,选择最短路径的路线,丢包重发需要的包,这个实际去看看滑动窗口协议就明白怎么丢包重发了。
  • 打赏
  • 举报
回复
求代码 !!!有的大神,求分享!!
lcf 2013-05-04
  • 打赏
  • 举报
回复
应该可以修行靠自身啦
  • 打赏
  • 举报
回复
嗯,有点意思了。
lcf 2013-05-04
  • 打赏
  • 举报
回复
引用 17 楼 u010475995 的回复:
用mina怎么实现这个?
不会用mina。。
lcf 2013-05-04
  • 打赏
  • 举报
回复
传输协议要你自己设计。所谓协议就是客户端和服务器端都认同的消息格式。 UDPDemo中包含了一个简易协议,那就是每个包开头都是一个int 所以你如果要实现更复杂的功能,就要定义更复杂的协议 在我这个例子里,每个包开头的int是逐个递增的。如果你想检测到丢包,那就在客户端写一个逻辑,来判断收到的这个包的这个int,是不是之前那个包的int值+1 至于重发,也就是你检测到丢包的时候,客户端要告诉服务器它丢包了,也是通过发送一个UDP包到服务器,然后服务器收到这个包之后开始回传丢失的那些包。代码其实可以从这个Demo改,只不过现在客户端和服务器端都要包含一个Reader一个Sender了
  • 打赏
  • 举报
回复
用mina怎么实现这个?
  • 打赏
  • 举报
回复
还有重发功能
  • 打赏
  • 举报
回复
我弄明白了你的这个demo,bufer的这些操作也明白了,先谢谢你。另外,我想问的是设计一个UDP传输协议,这个怎么体现出来?
lcf 2013-05-04
  • 打赏
  • 举报
回复
既然如此。。给你一个简易的开头吧。。 下面的代码每隔一秒发送一个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();
      }
    }
  }
}
  • 打赏
  • 举报
回复
这个代码不是我要的,你用的是io,我需要的nio写的!!!
  • 打赏
  • 举报
回复
嗯,谢谢,我先研究下。不到有重发功能么? 以及它的传输协议是什么,怎么设计的?
失意 2013-05-04
  • 打赏
  • 举报
回复
客户端:

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

失意 2013-05-04
  • 打赏
  • 举报
回复
这是我在课余没事的时候写的一个东西,不知道是否正确,但基本上应该可以完成相应的功能。支持文件和文件夹的传输,不过这里的包大小为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.mark(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.mark(10000);
						num++;
						num%=100;
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				bis.close();
				fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
  • 打赏
  • 举报
回复
。。。。意思我懂,怎么用代码实现它
u010558192 2013-05-04
  • 打赏
  • 举报
回复
我也不懂 判断丢包这种更不懂了 连网络中断后自动重连,俺都不懂
  • 打赏
  • 举报
回复
没有写过这方面的编程经验,最基本的包的传送和丢包都不太了解。知道个大概意思,但是写程序就不知所以然了。至于发送请求,怎么发就更不知道了!第一次写这种代码,不了解呀。。。你懂得,有点初学者的味道,想看看原始代码是怎么写的,以便有个大概这方面编程的代码思路。我真的很急。。。。唉
  • 打赏
  • 举报
回复
哦。。。我再想想
加载更多回复(8)

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧