网络编程-文件上传、模拟服务器案例实现

1.1 文件上传案例

 文件上传案例图解:

  1. 【客户端】输入流,从硬盘中读取文件数据到程序中。
  2. 【客户端】输出流,写出文件数据到服务端。
  3. 【服务端】输入流,读取文件数据到服务器程序。
  4. 【服务端】输出流,写出文件数据到服务器硬盘中。

1.客户端代码实现 

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/*
    文件上传案例客户端代码实现:暂不考虑多线程版
    思路:
        1.根据服务器端IP地址和端口号创建客户端Socket对象
        2.关闭Socket
        3.创建字节输入流关联目标文件:要上传的文件
        4.获得字节输出流对象
        5.定义字节数组存储读取到的文件数据
        6.定义整型变量用来记录读取到的字节个数
        7.循环读取
        8.利用out将图片数据输出到服务器端
        9.关闭流
        10.读完将读取到的文件数据发送到服务器端
        11.获得字节输入流对象
        12.读取服务器返回的上传状态文字
 */
public class TCPClient {
    public static void main(String[] args) throws Exception{
        //1.创建客户端Socket对象
        Socket socket = new Socket("172.20.10.2",9999);

        //3.创建字节输入流关联目标文件:要上传的文件
        FileInputStream fis = new FileInputStream("H:/aaa.jpg");
        //4.获得字节输出流对象
        OutputStream out = socket.getOutputStream();

        //5.定义字节数组存储读取到的文件数据
        byte[] buf = new byte[1024];

        //6.定义整型变量用来记录读取到的字节个数
        int len = -1;
        //7.循环读取
        while ((len=fis.read(buf))!=-1){
            //8.利用out将图片数据输出到服务器端
            out.write(buf,0,len);
        }
        //9.关闭流
        fis.close();
        //10.读完将读取到的文件数据发送到服务器端

        //11.获得字节输入流对象
        InputStream in = socket.getInputStream();

        //12.读取服务器返回的上传状态文字
        len = in.read(buf);
        System.out.println("len="+len);
        System.out.println(new String(buf,0,len));
        //2.关闭Socket
        socket.close();
    }
}

 2.服务器端代码实现

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

/*
    文件上传案例服务器端代码实现(先画出流程图,对着流程图写代码)
        实现步骤:
            1.创建ServerSocket对象
            2.关闭服务器(多线程不能关)
            3.等待客户端连接并获得相关的Socket对象
            4.获得字节输入流对象
            5.随机产生一个目标文件名
            6.创建随机数对象
            7.创建字节输出流关联目标文件
            8.创建字节输入流对象
            9.定义字节数组存储读取到客户端发送的图片数据
            10.定义整型变量接收实际读取到的字节个数
            11.循环读取
            12.获得字节输出流对象
            13.返回上传成功字符 
            14.关闭流和Socke           
 */
public class TCPServer {
    public static void main(String[] args) throws Exception{
        //1.创建ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(9999);

        //3.等待客户端连接并获得相关的Socket对象
        Socket socket = serverSocket.accept();

        //6.创建随机数对象
        int index = new Random().nextInt(324723894);
        
        //5.随机产生一个目标文件名
        String fileName = System.currentTimeMillis()+index+".jpg";

        //4.获得字节输入流对象
        InputStream fis = socket.getInputStream();
       
        //6.保存到硬盘里面的某个文件夹,需要拼接一个绝对路径
        //创建目标文件对象
        File destFile = new File("H:/aaa.jpg", fileName);

        //7.创建字节输出流关联目标文件
        FileOutputStream fos = new FileOutputStream(destFile);
        //8.创建字节输入流对象
        InputStream in = socket.getInputStream();

        //循环读取
        //9.定义字节数组存储读取到客户端发送的图片数据
        byte[] buf = new byte[1024];
        //10.定义整型变量接收实际读取到的字节个数
        int len = -1;

        //11.循环读取
        while ((len=in.read(buf))!=-1){
            //12.利用fos将图片数据输出到目标文件中
            fos.write(buf,0,len);
        }

        //12.获得字节输出流对象
        OutputStream out = socket.getOutputStream();
        //13.返回上传成功字符
        out.write("上传成功".getBytes());

        //14.关闭流和Socke
        fos.close();
        socket.close();
        
        //2.关闭服务器(多线程不能关)
        serverSocket.close();
    }
}

3.此时会出现一个问题,只考虑了上传成功的情况,那么我们如何处理上传失败的情况呢?先不抛异常,使用try...catch处理,把所有的代码都放在try...catch中。只要是进来了catch就出问题了,此时拿不到Socket,需要把前面两行代码放在外面(然后申明),然后可以利用JDK1.9新特性,将关闭服务器的代码放在小括号,即socket.close();serverSocket.close();放在小括号。

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

public class TCPServer {
    public static void main(String[] args) throws Exception{
        //1.创建ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(9999);

        //3.等待客户端连接并获得相关的Socket对象
        Socket socket = serverSocket.accept();
        try(socket;serverSocket){

            //6.创建随机数对象
            int index = new Random().nextInt(324723894);

            //5.随机产生一个目标文件名
            String fileName = System.currentTimeMillis()+index+".jpg";

            //4.获得字节输入流对象
            InputStream fis = socket.getInputStream();

            //6.保存到硬盘里面的某个文件夹,需要拼接一个绝对路径
            //创建目标文件对象
            File destFile = new File("H:/aaa.jpg", fileName);

            //7.创建字节输出流关联目标文件
            FileOutputStream fos = new FileOutputStream(destFile);
            //8.创建字节输入流对象
            InputStream in = socket.getInputStream();

            //循环读取
            //9.定义字节数组存储读取到客户端发送的图片数据
            byte[] buf = new byte[1024];
            //10.定义整型变量接收实际读取到的字节个数
            int len = -1;

            //11.循环读取
            while ((len=in.read(buf))!=-1){
                //12.利用fos将图片数据输出到目标文件中
                fos.write(buf,0,len);
            }

            //12.获得字节输出流对象
            OutputStream out = socket.getOutputStream();
            //13.返回上传成功字符
            out.write("上传成功".getBytes());

            //14.关闭流和Socke
            fos.close();

        }catch (Exception e){
            //12.获得字节输出流对象
            OutputStream out = socket.getOutputStream();
            //13.返回上传成功字符
            out.write("上传失败".getBytes());
        }

    }
}

客户端发数据没有将-1发过去,则读不到数据,这时需要在客户端加一行代码

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class TCPClient {
    public static void main(String[] args) throws Exception{
        //1.创建客户端Socket对象
        Socket socket = new Socket("172.20.10.2",9999);

        //3.创建字节输入流关联目标文件:要上传的文件
        FileInputStream fis = new FileInputStream("H:/aaa.jpg");
        //4.获得字节输出流对象
        OutputStream out = socket.getOutputStream();

        //5.定义字节数组存储读取到的文件数据
        byte[] buf = new byte[1024];

        //6.定义整型变量用来记录读取到的字节个数
        int len = -1;
        //7.循环读取
        while ((len=fis.read(buf))!=-1){
            //8.利用out将图片数据输出到服务器端
            out.write(buf,0,len);
        }

        //告诉服务器端数据传输完毕,相当于输出一个结束标记给服务器端
        socket.shutdownOutput();
        
        //9.关闭流
        fis.close();
        //10.读完将读取到的文件数据发送到服务器端

        //11.获得字节输入流对象
        InputStream in = socket.getInputStream();

        //12.读取服务器返回的上传状态文字
        len = in.read(buf);
        System.out.println("len="+len);
        System.out.println(new String(buf,0,len));
        //2.关闭Socket
        socket.close();
    }
}

文件上传案例服务器端代码实现:实现多用户上传(多线程)

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class TCPClient {
    public static void main(String[] args) throws Exception{
        //1.创建客户端Socket对象
        Socket socket = new Socket("172.20.10.2",9999);

        //3.创建字节输入流关联目标文件:要上传的文件
        FileInputStream fis = new FileInputStream("H:/aaa.jpg");
        //4.获得字节输出流对象
        OutputStream out = socket.getOutputStream();

        //5.定义字节数组存储读取到的文件数据
        byte[] buf = new byte[1024];

        //6.定义整型变量用来记录读取到的字节个数
        int len = -1;
        //7.循环读取
        while ((len=fis.read(buf))!=-1){
            //8.利用out将图片数据输出到服务器端
            out.write(buf,0,len);
        }

        //告诉服务器端数据传输完毕,相当于输出一个结束标记给服务器端
        socket.shutdownOutput();

        //9.关闭流
        fis.close();
        //10.读完将读取到的文件数据发送到服务器端

        //11.获得字节输入流对象
        InputStream in = socket.getInputStream();

        //12.读取服务器返回的上传状态文字
        len = in.read(buf);
        System.out.println("len="+len);
        System.out.println(new String(buf,0,len));
        //2.关闭Socket
        socket.close();
    }
}
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;

public class TCPServer {
    public static void main(String[] args) throws Exception{
        //1.创建ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(9999);

        System.out.println("服务器开启");
        //使用死循环保证服务器永不关闭
        while (true){
            //3.等待客户端连接并获得相关的Socket对象
            Socket socket = serverSocket.accept();
            //开启线程执行上传操作
            new Thread(()->{
                try(socket){

                    //6.创建随机数对象
                    int index = new Random().nextInt(324723894);

                    //5.随机产生一个目标文件名
                    String fileName = System.currentTimeMillis()+index+".jpg";

                    //4.获得字节输入流对象
                    InputStream fis = socket.getInputStream();

                    //6.保存到硬盘里面的某个文件夹,需要拼接一个绝对路径
                    //创建目标文件对象
                    File destFile = new File("H:/aaa.jpg", fileName);

                    //7.创建字节输出流关联目标文件
                    FileOutputStream fos = new FileOutputStream(destFile);
                    //8.创建字节输入流对象
                    InputStream in = socket.getInputStream();

                    //循环读取
                    //9.定义字节数组存储读取到客户端发送的图片数据
                    byte[] buf = new byte[1024];
                    //10.定义整型变量接收实际读取到的字节个数
                    int len = -1;

                    //11.循环读取
                    while ((len=in.read(buf))!=-1){
                        //12.利用fos将图片数据输出到目标文件中
                        fos.write(buf,0,len);
                    }

                    //12.获得字节输出流对象
                    OutputStream out = socket.getOutputStream();
                    //13.返回上传成功字符
                    out.write("上传成功".getBytes());
                    //获得客户端ip地址
                    String clientIP = socket.getInetAddress().getHostAddress();

                    System.out.println("恭喜IP为:"+clientIP+"上传成功");

                    //14.关闭流和Socke
                    fos.close();

                }catch (Exception e){
                    try {
                        //12.获得字节输出流对象
                        OutputStream out = socket.getOutputStream();
                        //13.返回上传成功字符
                        out.write("上传失败".getBytes());
                    }catch (Exception ee){
                        ee.printStackTrace();
                    }
                }

            }).start();
        }


    }
}

模拟服务器案例:

未完,待续......

猜你喜欢

转载自blog.csdn.net/Huangyuhua068/article/details/81612588