Java-TCP协议:模拟用户文件上传与模拟WEB服务器

本文深入解析了单用户和多用户环境下的文件上传流程,包括直接上传、上传并接收反馈,以及多用户并发上传的实现方式。同时,展示了如何通过多线程技术提升上传效率,并附带了一个模拟WEB服务器的案例,演示了如何处理来自浏览器的文件请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、单用户文件上传

流程示意图:

在这里插入图片描述

客户端代码:(此处以传输一张图片为例)

public static void main(String[] args) {
        //建立连接
        try (Socket socket = new Socket("127.0.0.1", 8086)) {
            //网络输出流发送数据
            OutputStream os = socket.getOutputStream();
            //文件输入流读取要发送文件
            System.out.println("文件开始传输...");
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\1.bmp"));
            //循环读取文件,并发向服务端发送
            byte[] bytes = new byte[1024 * 8];
            int len = 0;
            while ((len = bis.read(bytes))!=-1){
                os.write(bytes,0,len);
            }
            os.close();
            bis.close();
            System.out.println("文件传输成功");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务器代码:

public static void main(String[] args) {
        //监听端口
        try (ServerSocket server = new ServerSocket(8086)) {
            //等待客户端进行访问
            System.out.println("服务器已开启,等待客户端连接");
            Socket sc = server.accept();
            //网络输入流接收客户端数据
            InputStream is = sc.getInputStream();
            //文件输出流
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.bmp"));
            //循环写入文件
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = is.read(bytes))!=-1){
                bos.write(bytes,0,len);
            }
            is.close();
            bos.close();
            System.out.println("服务器处理完毕");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2、文件上传并发送反馈

客户端:

public static void main(String[] args) {
        //建立连接
        try (Socket socket = new Socket("127.0.0.1", 8086)) {
            //网络输出流
            OutputStream out = socket.getOutputStream();
            //文件输入流
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\1.bmp"));
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = bis.read(bytes))!=-1){
                out.write(bytes,0,len);
            }

            //向网络发送一个结束标记
            socket.shutdownOutput();
            System.out.println("客户端上传完毕,等待接收反馈");
            //接收反馈
            InputStream is = socket.getInputStream();
            byte[] bytes1 = new byte[1024];
            int len1 = is.read(bytes1);
            System.out.println("客户端收到反馈:"+new String(bytes1,0,len1));

            out.close();
            bis.close();
            is.close();
            System.out.println("客户端上传完毕");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务器:

public static void main(String[] args) {
        //监听端口
        try (ServerSocket server = new ServerSocket(8086)) {
            //等待连接
            Socket socket = server.accept();
            //获取网络输入流
            InputStream is = socket.getInputStream();
            //文件输出流
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2_copy.bmp"));
            //开始循环从网络接收
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = is.read(bytes))!=-1){
                bos.write(bytes,0,len);
            }
            System.out.println("服务器上传完毕,开始发送反馈");
            //发送反馈
            OutputStream netout = socket.getOutputStream();
            netout.write("收到文件".getBytes());

            is.close();
            bos.close();
            netout.close();
            System.out.println("服务器处理完毕");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3、多用户上传文件

图示:

在这里插入图片描述

使用多线程进行用户文件上传,就可以同时有多个用户进行上传和接收反馈

客户端代码:

public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new CilentThread().start();
        }
    }

客户端线程代码:

public class CilentThread extends Thread{
    @Override
    public void run() {
        //建立连接
        try (Socket socket = new Socket("127.0.0.1", 8086)) {
            //网络输出流
            OutputStream netout = socket.getOutputStream();
            //文件输入流读取文件
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("2.bmp"));
            //循环读取文件,并向网络发送
            byte[] bytes = new byte[1024 * 8];
            int len = 0;
            while ((len = bis.read(bytes))!=-1){
                netout.write(bytes,0,len);
            }
            System.out.println("发送结束,等待接收反馈");
            //结束标记
            socket.shutdownOutput();
            //接收反馈
            InputStream is = socket.getInputStream();
            byte[] bytes1 = new byte[1024];
            int len1 = is.read(bytes1);
            System.out.println("客户端接收反馈:"+new String(bytes1,0,len1));
            //关闭流
            netout.close();
            bis.close();
            is.close();
            System.out.println("客户端上传结束!");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务端代码:

public static void main(String[] args) {
        //监听端口
        try (ServerSocket server = new ServerSocket(8086)) {
            while (true){
                //等待连接
                Socket socket = server.accept();
                //开启线程
                new ServerThread(socket).start();
                //休息100毫秒
                Thread.sleep(100);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

服务器线程代码:

public class ServerThread extends Thread {
    private Socket socket;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        //网络输入流
        try {InputStream netIn = socket.getInputStream();
            //文件输出流
            //以系统毫秒值为每个文件的名字
            Long m = System.currentTimeMillis();
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(m+".bmp"));
            //循环从网络读取文件
            byte[] bytes = new byte[1024 * 8];
            int len = 0;
            while ((len = netIn.read(bytes))!=-1){
                bos.write(bytes,0,len);
            }
            //发送反馈
            OutputStream netout = socket.getOutputStream();
            netout.write(("接收完毕,文件名:"+ m +".bmp").getBytes());
            //关闭资源
            netIn.close();
            bos.close();
            netout.close();
            System.out.println("服务器上传:"+m+".bmp文件完毕");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4、模拟WEB服务器-案例说明

在这里插入图片描述

5、模拟WEB服务器-案例实现

在浏览器输入开启下面模拟WEB服务器的ip:端口号+要获取的内容

例如:127.0.0.1:8086/img/meinv1.jpg获取meinv1.jpg图片

public class Server {
    public static void main(String[] args) throws IOException {
        //1.监听端口
        ServerSocket server = new ServerSocket(8086);
        while (true) {
            //2.等待连接
            Socket socket = server.accept();
            new Thread(()->{
                System.out.println("有客户端连接成功....");
                //3.接收信息
                InputStream in = null;
                try {
                    in = socket.getInputStream();
                    //将字节流转换为:字符缓冲流
                    BufferedReader bufIn = new BufferedReader(new InputStreamReader(in));
                    String row = bufIn.readLine();//"GET /img/meinv4.jpg HTTP/1.1"()
                    System.out.println("请求行:" + row);
                    if (row == null) {
                        socket.close();
                        return;
                    }
                    if (!row.contains("meinv")) {
                        socket.close();
                        return;
                    }
                    String[] arr = row.split(" ");
                    if (arr.length < 3) {
                        socket.close();
                        return;
                    }
                    String path = arr[1];//"/img/meinv4.jpg"
                    path = path.substring(1);//"img/meinv4.jpg"

                    //4.向客户端响应“头”信息--给浏览器
                    OutputStream out = socket.getOutputStream();
                    out.write("HTTP/1.1 200 OK\r\n".getBytes());//固定写法
                    out.write("Content-type:image/jpeg\r\n".getBytes());//image/jpeg:表示内容是:图片,如果是网页:text/html
                    out.write("\r\n".getBytes());

                    System.out.println(path);

                    //5.响应图片
                    try (
                            FileInputStream fileIn = new FileInputStream(path);
                    ) {
                        System.out.println("开始响应文件:" + path);
                        byte[] byteArray = new byte[1024];
                        int len = 0;
                        while ((len = fileIn.read(byteArray)) != -1) {
                            //向客户端输出
                            out.write(byteArray, 0, len);
                        }
                    } catch (Exception e) {
                        System.out.println("文件不存在:" + path);
                    }
                    //断开连接
                    bufIn.close();
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值