IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 通过Socket实现文件上传/上传文件 -> 正文阅读

[网络协议]通过Socket实现文件上传/上传文件

整个功能的实现步骤

1.客户端使用本地的字节输入流读取被上传的文件数据
2.客户端使用网络字节输出流,将读取到的文件数据发送给服务端
3.服务端使用网络字节输入流读取客户端发送过来的文件数据
4.服务端使用本地字节输出流将读取到的文件数据写入到指定的服务器本地文件中(例如,保存到目录 upload 下面)
5.服务端使用网络字节输出流,给客户端回写一段文字:“上传成功”
6.客户端使用网络字节输入流,读取服务端返回的数据
7.释放资源

注意:
1.客户端和服务端对本地硬盘进行读写,需要使用自己创建的 IO 流,称为本地流
2.客户端和服务端之间进行数据读写,必须使用 Socket 中提供的 IO 流,称为网络流

客户端的实现步骤

1.创建一个本地字节输入流对象(即 FileInputStream),构造方法中绑定要读取的数据源
2.创建一个客户端对象(即 Socket 对象),构造方法中绑定 IP 和端口号
3.使用 Socket 对象的方法 getOutputStream,获取网络字节输出流对象
4.使用 FileInputStream 对象的方法 read 读取要上传的文件数据
5.使用网络字节输出流对象的方法 write,将读取到的文件数据发送到服务端
6.使用 Socket 对象的方法 getInputStream 获取网络字节输入流对象
7.使用网络字节输入流对象的方法 read 读取服务端回写的数据
8.释放资源(FileInputStream、Socket)

服务端的实现步骤

1.创建一个服务端对象(即 ServerSocket),并且向系统要指定的端口号
2.使用服务端对象的方法 accept 获取请求的客户端对象(即请求连接的 Socket 对象)
3.使用 Socket 对象的方法 getInputStream 获取网络字节输入流
4.判断服务端的目标目录路径是否存在,若不存在要创建此目录
5.创建一个本地字节输出流对象(即 FileOutputStream),构造方法中要绑定写入数据的目标文件路径
6.使用网络字节输入流的方法 read 读取客户端发送过来的文件数据
7.使用 FileOutputStream 对象的方法 write 将读取到文件数据写入到服务器本地文件中
8.使用 Socket 对象的方法 getOutputStream 获取网络字节输出流对象
9.使用网络字节输出流对象的方法 write 给客户端发送一段文字:文件上传成功!
10.释放资源(FileOutputStream、Socket、ServerSocket)

示例代码

客户端代码:

package priv.lwx.javaex.fileupload;

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

/**
 * @ClassName TCPClient
 * @Description 客户端读取本地的文件数据,发送给服务端
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/5 下午4:50
 */
public class TCPClient {
  public static void main(String[] args) throws IOException {
    // 1.创建一个本地字节输入流对象(即 `FileInputStream`),构造方法中绑定要读取的数据源
    FileInputStream fis = new FileInputStream("/Users/liaowenxiong/desktop/test/1.jpeg");
    // 2.创建一个客户端对象(即 Socket 对象),构造方法中绑定 IP 和端口号
    Socket socket = new Socket("127.0.0.1", 8888);
    // 3.使用 Socket 对象的方法 getOutputStream,获取网络字节输出流对象
    OutputStream os = socket.getOutputStream();
    // 4.使用 FileInputStream 对象的方法 read 读取要上传的文件数据
    byte[] bytes = new byte[1024];
    int i = 0;
    while ((i = fis.read(bytes)) != -1) {
      // 5.使用网络字节输出流对象的方法 write,将读取到的文件数据发送到服务端
      os.write(bytes, 0, i); // i表示获取数组元素的个数
    }
    // 禁用此套接字的输出流,此时会写入一个终止标记,这样服务端就可以读取到此标记,就不会出现阻塞的问题了
    // 终止标记表示输出流写出的数据已经没有了,服务端解析到这个标记后就,有关的线程就不会一直处于等待接收
    // 数据的状态
    socket.shutdownOutput();
    // 6.使用 Socket 对象的方法 getInputStream 获取网络字节输入流对象
    InputStream is = socket.getInputStream();
    // 7.使用网络字节输入流对象的方法 read 读取服务端回写的数据到指定的字节数组中
    i = is.read(bytes);// 读取几个字节,就返回几
      // 将字节数组中的数据转换成字符串,并打印到控制台
    System.out.println(new String(bytes, 0, i));
    // 8.释放资源(FileInputStream、Socket)
    fis.close();
    socket.close();
  }
}

服务端代码:

package priv.lwx.javaex.fileupload;

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

/**
 * @ClassName TCPServer
 * @Description 服务端读取客户端发送过来的文件数据,并写入到指定的服务器本地的文件中
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/5 下午7:38
 */
public class TCPServer {
    public static void main(String[] args) throws IOException {
        // 1.创建一个服务端对象(即 ServerSocket),并且向系统要指定的端口号
        ServerSocket server = new ServerSocket(8888);
        // 2.使用服务端对象的方法 accept 获取请求的客户端对象(即请求连接的 Socket 对象)
        Socket socket = server.accept();
        // 3.使用 Socket 对象的方法 getInputStream 获取网络字节输入流
        InputStream is = socket.getInputStream();
        // 4.判断服务端的目标目录路径是否存在,若不存在要创建此目录
        File file = new File("/Users/liaowenxiong/desktop/test/upload");
        if (!file.exists()) {
            file.mkdirs();
        }
        // 5.创建一个本地字节输出流对象(即 FileOutputStream),构造方法中要绑定写入数据的目标文件路径
        FileOutputStream fos = new FileOutputStream(file + File.separator + "1.jpeg");

        // 6.使用网络字节输入流的方法 read 读取客户端发送过来的文件数据
        byte[] bytes = new byte[1024];
        int i = 0;
        while ((i = is.read(bytes)) != -1) {
            // 7.使用 FileOutputStream 对象的方法 write 将读取到文件数据写入到服务器本地文件中
            fos.write(bytes, 0, i);
        }

        // 8.使用 Socket 对象的方法 getOutputStream 获取网络字节输出流对象
        OutputStream ops = socket.getOutputStream();
        // 9.使用网络字节输出流对象的方法 write 给客户端发送一段文字:文件上传成功!
        ops.write("文件上传成功!".getBytes());
        // 10.释放资源(FileOutputStream、Socket、ServerSocket)
        fos.close();
        socket.close();
        server.close();
    }

}

服务端的升级版本一:

package priv.lwx.javaex.fileupload;

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

/**
 * @ClassName TCPServer
 * @Description 服务端读取客户端发送过来的文件数据,并写入到指定的服务器本地的文件中
 *              在 TCPServer 的基础上优化两个地方
 *              1.自定义文件名,每次上传文件的文件名都不同
 *              2.让服务端一直处于监听状态,这样就可以一直上传图片
 *
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/5 下午7:38
 */
public class TCPServer02 {
    public static void main(String[] args) throws IOException {
        // 1.创建一个服务端对象(即 ServerSocket),并且向系统要指定的端口号
        ServerSocket server = new ServerSocket(8888);
        // 2.使用服务端对象的方法 accept 获取请求的客户端对象(即请求连接的 Socket 对象)
        // 通过死循环,可以让服务端一直处于监听状态,只要有客户端请求连接,服务端就可以响应连接请求
        while (true) {
            Socket socket = server.accept();
            // 3.使用 Socket 对象的方法 getInputStream 获取网络字节输入流
            InputStream is = socket.getInputStream();
            // 4.判断服务端的目标目录路径是否存在,若不存在要创建此目录
            File file = new File("/Users/liaowenxiong/desktop/test/upload");
            if (!file.exists()) {
                file.mkdirs();
            }
            // 自定义文件名的规则
            String fileName = System.currentTimeMillis() + (new Random().nextInt(9) + 1) + ".jpeg";
            // 5.创建一个本地字节输出流对象(即 FileOutputStream),构造方法中要绑定写入数据的目标文件路径
            FileOutputStream fos = new FileOutputStream(file + File.separator + fileName);

            // 6.使用网络字节输入流的方法 read 读取客户端发送过来的文件数据
            byte[] bytes = new byte[1024];
            int i = 0;
            while ((i = is.read(bytes)) != -1) {
                // 7.使用 FileOutputStream 对象的方法 write 将读取到文件数据写入到服务器本地文件中
                fos.write(bytes, 0, i);
            }

            // 8.使用 Socket 对象的方法 getOutputStream 获取网络字节输出流对象
            OutputStream ops = socket.getOutputStream();
            // 9.使用网络字节输出流对象的方法 write 给客户端发送一段文字:文件上传成功!
            ops.write("文件上传成功!".getBytes());
            // 10.释放资源(FileOutputStream、Socket、ServerSocket)
            fos.close();
            socket.close();
            // 服务端不停止,服务端资源不要释放
            // server.close();
        }
    }

}

服务端的升级版本二:

package priv.lwx.javaex.fileupload;

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

/**
 * @ClassName TCPServer
 * @Description 服务端读取客户端发送过来的文件数据,并写入到指定的服务器本地的文件中
 *              在 TCPServer02 基础上优化
 *              使用多线程技术,提高程序的效率,有一个客户端上传文件,就开启一个线程完成文件的上传
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/5 下午7:38
 */
public class TCPServer03 {
    public static void main(String[] args) throws IOException {
        // 1.创建一个服务端对象(即 ServerSocket),并且向系统要指定的端口号
        ServerSocket server = new ServerSocket(8888);
        // 2.使用服务端对象的方法 accept 获取请求的客户端对象(即请求连接的 Socket 对象)
        // 通过死循环,可以让服务端一直处于监听状态,只要有客户端请求连接,服务端就可以响应连接请求
        while (true) {
            Socket socket = server.accept();
            // 使用多线程技术,提高文件上传的效率,有一个客户端上传文件,就开启一个线程完成文件的上传
            new Thread(new Runnable() {
                // run 方法里面完成文件数据的读取和写入
                @Override
                public void run() {
                    FileOutputStream fos = null;
                    try {
                        // 3.使用 Socket 对象的方法 getInputStream 获取网络字节输入流
                        InputStream is = socket.getInputStream();
                        // 4.判断服务端的目标目录路径是否存在,若不存在要创建此目录
                        File file = new File("/Users/liaowenxiong/desktop/test/upload");
                        if (!file.exists()) {
                            file.mkdirs();
                        }
                        // 自定义文件名的规则
                        String fileName = System.currentTimeMillis() + (new Random().nextInt(9) + 1) + ".jpeg";
                        // 5.创建一个本地字节输出流对象(即 FileOutputStream),构造方法中要绑定写入数据的目标文件路径
                        fos = new FileOutputStream(file + File.separator + fileName);

                        // 6.使用网络字节输入流的方法 read 读取客户端发送过来的文件数据
                        byte[] bytes = new byte[1024];
                        int i = 0;
                        while ((i = is.read(bytes)) != -1) {
                            // 7.使用 FileOutputStream 对象的方法 write 将读取到文件数据写入到服务器本地文件中
                            fos.write(bytes, 0, i);
                        }

                        // 8.使用 Socket 对象的方法 getOutputStream 获取网络字节输出流对象
                        OutputStream ops = socket.getOutputStream();
                        // 9.使用网络字节输出流对象的方法 write 给客户端发送一段文字:文件上传成功!
                        ops.write("文件上传成功!".getBytes());
                        // 10.释放资源(FileOutputStream、Socket、ServerSocket)

                    } catch (IOException e) {
                        // System.out.println(e);
                        e.printStackTrace();
                    } finally {
                        try {
                            fos.close();
                            socket.close();
                            // 服务端不停止,服务端资源不要释放
                            // server.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }
                }
            }).start();

        }
    }

}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:59:55  更:2022-02-28 16:03:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:44:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码