Java实现 Windows Socket编程 UDP实现大文件的传输

一、实验要求

1、在服务器端,接收客户端传输的数据流,并按 IP 地址保存在服务器端(文
件名重复的,可以覆盖)。
2、如果传输过程中服务器端发现客户端断开,服务器端应删除文件,并在屏幕
上提示,如“
IP 1.2.3.4 发来 abcd.txt 文件过程中失去连接。”。如果客户端发
现服务器端不工作,客户端应有提示“服务器
1.2.3.5:62345 失去连接”。

三、具体代码实现

1、server端

package indi.tangkai.internet.udp;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

public class Server extends Thread {

	// 文件的保存路径
	private String fileDir;
	// socket服务器端口号
	private int port;

	public String getFileDir() {
		return fileDir;
	}

	public void setFileDir(String fileDir) {
		this.fileDir = fileDir;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public static void main(String[] args) {
		Server server = new Server();
		server.setFileDir("E:\\test\\download\\");
		server.setPort(9005);
		server.start();
	}

	/**
	 * 文件下载
	 */
	@Override
	public void run() {

		int bufferSize = 8192;
		byte[] buf = new byte[bufferSize];

		DatagramPacket dpk = null;
		DatagramSocket dsk = null;

		DataOutputStream fileOut = null;//文件输出流
		long passedlen = 0;//完成传输的大小
		long len = 0;//文件的大小
		
		int readSize = 0;//每次读取数据的大小
		
		String fileName = null;//接受的文件名

		try {
			dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName("localhost"), port));  
			dsk = new DatagramSocket(port + 1, InetAddress.getByName("localhost"));  
			
			// public Socket accept() throws
			// IOException侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。
			System.out.println("等待客户端链接");
			
			dsk.receive(dpk);
			
			
			// 本地保存路径,文件名会自动从服务器端继承而来。
			// 获取文件名
			
			fileName = new String(buf).trim();
			
			fileDir = fileDir + dpk.getAddress().toString().split("/")[1];
			
			File file = new File(fileDir);
			
			if(!file.exists())
			{
				file.mkdir();
			}
			
			String filePath = fileDir + "\\" + fileName;
						
			dsk.receive(dpk);
			
			System.out.println("buf文件的路径" + filePath + "\n");
			
			file = new File(filePath);
			
			if(!file.exists())
			{
				file.createNewFile();
			}
			
			fileOut = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
			
			len = Long.parseLong(new String(buf, 0, dpk.getLength()));

			System.out.println("开始接收文件!" + "\n");
			
			
			dsk.receive(dpk);
			while ((readSize = dpk.getLength()) != 0) {

				passedlen += readSize; 
				//在图形化界面,该部分可以用来作为进度条
				//System.out.println("文件接收了" + (passedlen * 100 / len) + "%\n");
				fileOut.write(buf, 0, readSize);
				fileOut.flush();
				dsk.receive(dpk);
			}
			
			if(passedlen != len)
			{
				System.out.printf("IP:%s发来的%s传输过程中失去连接\n",dpk.getAddress(),fileName);
				file.delete();//将缺损文件删除
			}
			else
				System.out.println("接收完成,文件存为" + filePath + "\n");


		} catch (Exception e) {
			System.out.println("接收消息错误" + "\n");
			e.printStackTrace();
			return;
		}finally{
			if(fileOut != null)
				try {
					fileOut.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			if(dsk != null)
				dsk.close();
			if(passedlen != len)
			{
				System.out.printf("IP:%s发来的%s传输过程中失去连接\n",dpk.getAddress(),fileName);
			}
		}
	}

}

2、client端

package indi.tangkai.internet.udp;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;


public class Client {
    // 上传的文件路径,可在main函数中修改
    private String filePath;
    // socket服务器地址和端口号
    private String host;
    private int port;

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }
    
    public static void main(String[] args) {
        Client client = new Client();
        client.setHost("127.0.0.1");
        client.setPort(9005);
        client.setFilePath("E:\\test\\upload\\");
        client.uploadFile("test.rar");
    }

    /**
     * 客户端文件上传
     * @param fileName 文件名
     */
    public void uploadFile(String fileName) {

        DatagramSocket dsk = null;
        DatagramPacket dpk = null;
        DataInputStream fis = null;
        try {
            dsk = new DatagramSocket(port, InetAddress.getByName(host));
            int bufferSize = 8192;
            byte[] buf = new byte[bufferSize];
            dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName(host), port + 1)); 
            // 选择进行传输的文件
            File fi = new File(filePath + fileName);
            System.out.println("文件长度:" + (int) fi.length());
            
            fis = new DataInputStream(new FileInputStream(filePath + fileName));
            
            buf = fi.getName().getBytes();
            
            dpk.setData(buf, 0, fileName.length());
            dsk.send(dpk);
            
            String fileLen = Long.toString((long) fi.length());
            
            buf = fileLen.getBytes();            
            System.out.println("buf文件长度"+new String(buf));
            
            dpk.setData(buf, 0, fileLen.length());
            dsk.send(dpk);
            
            while (true) {
                int read = 0;
                if (fis != null) {
                    read = fis.read(buf);
                }

                if (read == -1) {
                    break;
                }
                dpk.setData(buf, 0, read);
                dsk.send(dpk);
            }
            //给服务器发布一个终止信号
            dpk.setData(buf, 0, 0);
            dsk.send(dpk);
            System.out.println("文件传输完成");
        } catch (Exception e) {
    		System.out.println("服务器"+host+":"+port+"失去连接");
            e.printStackTrace();
        }finally{
        	try{
        		if(fis!=null)
        			fis.close();
        		if(dsk != null)
        			dsk.close();
        	}catch(IOException e){
        		e.printStackTrace();
        	}
        }
    }
}

四、运行截图示例

1、server端



2、client端


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值