Java语言进阶:TCP实现文件上传

Java语言进阶:TCP实现文件上传


TCP实现文件上传案例

需求

  • 使用TCP协议, 通过客户端向服务器上传一个文件

分析

  1. 【客户端】输入流,从硬盘读取文件数据到程序中。

  2. 【客户端】输出流,写出文件数据到服务端。

  3. 【服务端】输入流,读取文件数据到服务端程序。

  4. 【服务端】输出流,写出文件数据到服务器硬盘中。

  5. 【服务端】获取输出流,回写数据。

  6. 【客户端】获取输入流,解析回写数据。
    在这里插入图片描述

实现

拷贝文件
public class Client {
    public static void main(String[] args) throws Exception {
        // 1.创建输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day12\\aaa\\hb.jpg");

        // 2.创建Socket对象,指定要连接的服务器的ip地址和端口号
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);

        // 3.通过Socket对象获得输出流,关联连接通道
        OutputStream os = socket.getOutputStream();

        // 4.定义变量,用来存储读取到的字节数据
        byte[] bys = new byte[8192];
        int len;

        // 5.循环读取
        while ((len = fis.read(bys)) != -1) {
            // 6.在循环中,写出数据到通道中
            os.write(bys,0,len);
        }
        // 7.释放资源
        socket.close();
        fis.close();
    }
}
public class Server {
    public static void main(String[] args) throws Exception {
        // 1.创建ServerSocket对象,指定端口号 8888
        ServerSocket ss = new ServerSocket(8888);

        // 2.使用ServerSocket对象调用accept()方法,接收请求,建立连接,返回Socket对象
        Socket socket = ss.accept();

        // 3.通过返回的Socket对象获得输入流,关联连接通道
        InputStream is = socket.getInputStream();

        // 4.创建输出流对象,关联目的地文件路径
        FileOutputStream fos = new FileOutputStream("day12\\aaa\\hbCopy2.jpg");

        // 5.定义变量,用来存储读取到的字节数据
        byte[] bys = new byte[8192];
        int len;

        // 6.循环读取
        while ((len = is.read(bys)) != -1) {
            // 7.在循环中,写出数据目的文件中
            fos.write(bys,0,len);
        }
        // 8.释放资源
        fos.close();
        socket.close();
    }
}
文件上传成功后服务器回写字符串数据
// 客户端
public class Client {
    public static void main(String[] args) throws Exception {
        // 1.创建输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day12\\aaa\\hb.jpg");

        // 2.创建Socket对象,指定要连接的服务器的ip地址和端口号
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);

        // 3.通过Socket对象获得输出流,关联连接通道
        OutputStream os = socket.getOutputStream();

        // 4.定义变量,用来存储读取到的字节数据
        byte[] bys = new byte[8192];
        int len;

        // 5.循环读取
        while ((len = fis.read(bys)) != -1) {
            // 6.在循环中,写出数据到通道中
            os.write(bys, 0, len);
        }

        // - 在文件上传时,客户端从文件中读不到数据,就会停止发送。
        // 但是服务器端不知道客户端停止了,所以会一直等待接收数据。
		// 解决办法:在客户端调用s.shutdownOutput();通知服务器端发送结束了。
        socket.shutdownOutput();// 注意

        System.out.println("============客户端开始接受服务器返回的数据==============");
        // 7.通过Socket对象获取输入流,关联连接通道
        InputStream is = socket.getInputStream();

        // 8.读取服务器回写的数据
        int read = is.read(bys);// 卡死  读取服务器写回的数据,但是服务器又没有写回数据
        // 9.打印服务器回写的数据
        System.out.println("服务器回写的数据是:" + new String(bys, 0, read));

        // 10.释放资源
        socket.close();
        fis.close();
    }
}
// 服务器
public class Server {
    public static void main(String[] args) throws Exception {
        // 1.创建ServerSocket对象,指定端口号 8888
        ServerSocket ss = new ServerSocket(8888);

        // 2.使用ServerSocket对象调用accept()方法,接收请求,建立连接,返回Socket对象
        Socket socket = ss.accept();

        // 3.通过返回的Socket对象获得输入流,关联连接通道
        InputStream is = socket.getInputStream();

        // 4.创建输出流对象,关联目的地文件路径
        FileOutputStream fos = new FileOutputStream("day12\\aaa\\hbCopy5.jpg");

        // 5.定义变量,用来存储读取到的字节数据
        byte[] bys = new byte[8192];
        int len;

        // 6.循环读取
        while ((len = is.read(bys)) != -1) {
            // 7.在循环中,写出数据目的文件中
            fos.write(bys, 0, len);
        }

        System.out.println("======服务器开始回写数据给客户端=======");
        // 7.通过socket对象获取输出流,关联连接通道
        OutputStream os = socket.getOutputStream();

        // 8.写出数据到通道中
        os.write("恭喜您,上传成功!".getBytes());

        // 9.释放资源
        fos.close();
        socket.close();
    }
}


优化文件上传案例

1.文件名固定----->优化 自动生成唯一的文件名
2.服务器只能接受一次 ----> 优化 死循环去接收请求,建立连接
3.例如:如果张三先和服务器建立连接,上传了一个2GB字节大小的文件
- 李四后和服务器建立连接,上传了一个2MB字节大小的文件
- 李四就必须等张三上传完毕,才能上传文件

优化---->多线程优化
张三上传文件,开辟一条线程
李四上传文件,开辟一条线程

代码块:
// 服务器
public class Server {
    // year+"年"+month+"月"+day+"日"+....+"毫秒"
    public static void main(String[] args) throws Exception {
        // 1.创建ServerSocket对象,指定端口号 8888
        ServerSocket ss = new ServerSocket(8888);

        while (true) {
            // 2.使用ServerSocket对象调用accept()方法,接收请求,建立连接,返回Socket对象
            Socket socket = ss.accept();

           new Thread(new Runnable() {
               @Override
               public void run() {

                   try {
                       // 3.通过返回的Socket对象获得输入流,关联连接通道
                       InputStream is = socket.getInputStream();

                       // 4.创建输出流对象,关联目的地文件路径
                       FileOutputStream fos = new FileOutputStream("day12\\aaa\\"+System.currentTimeMillis()+".jpg");

                       // 5.定义变量,用来存储读取到的字节数据
                       byte[] bys = new byte[8192];
                       int len;

                       // 6.循环读取
                       while ((len = is.read(bys)) != -1) {
                           // 7.在循环中,写出数据目的文件中
                           fos.write(bys, 0, len);
                       }

                       System.out.println("======服务器开始回写数据给客户端=======");
                       // 7.通过socket对象获取输出流,关联连接通道
                       OutputStream os = socket.getOutputStream();

                       // 8.写出数据到通道中
                       os.write("恭喜您,上传成功!".getBytes());

                       // 9.释放资源
                       fos.close();
                       socket.close();

                   } catch (IOException e) {

                   }
               }
           }).start();

        }
    }
}
// 客户端
public class Client {
    public static void main(String[] args) throws Exception {
        // 1.创建输入流对象,关联数据源文件路径
        FileInputStream fis = new FileInputStream("day12\\aaa\\hb.jpg");

        // 2.创建Socket对象,指定要连接的服务器的ip地址和端口号
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);

        // 3.通过Socket对象获得输出流,关联连接通道
        OutputStream os = socket.getOutputStream();

        // 4.定义变量,用来存储读取到的字节数据
        byte[] bys = new byte[8192];
        int len;

        // 5.循环读取
        while ((len = fis.read(bys)) != -1) {
            // 6.在循环中,写出数据到通道中
            os.write(bys, 0, len);
        }

        // 想办法,告诉服务器,我客户端写完了数据,我再也不会写数据了
        socket.shutdownOutput();// 注意

        System.out.println("============客户端开始接受服务器返回的数据==============");
        // 7.通过Socket对象获取输入流,关联连接通道
        InputStream is = socket.getInputStream();

        // 8.读取服务器回写的数据
        int read = is.read(bys);
        // 9.打印服务器回写的数据
        System.out.println("服务器回写的数据是:" + new String(bys, 0, read));

        // 10.释放资源
        socket.close();
        fis.close();
    }
}

笔记如有错误之处,请各位大佬指正,欢迎评论留言,不胜感激!!!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值