网络通信——文件上传案例

目录

实现客户端与服务端的文件传输

Server服务端代码:

Client客户端代码:

文件传输案例的优化

优化后Server服务端代码:


实现客户端与服务端的文件传输

该案例需要一个客户端和一个服务端;其本质和文件的复制十分相似,但在客户端本地文件的发送和服务端文件的接收需要使用socket网络流进行传输

Server服务端代码:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class TCPServer {

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8889);
        Socket socket = server.accept();
        InputStream is = socket.getInputStream();
        //这个用于在本地盘中创建文件夹来存放图片
        File file = new File("D:\\桌面\\接收");
        if (!file.exists()) {
            file.mkdirs();
        }
        //进行文件的下载(相当于复制)
        FileOutputStream fos = new FileOutputStream(file+"\\接收的图片.jpg");
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = is.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
        //回写信息
        socket.getOutputStream().write("上传成功".getBytes(StandardCharsets.UTF_8));
        fos.close();
        socket.close();
        server.close();
    }
}

Client客户端代码:

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

/**
 * 客户端:读取本地文件 ,上传到服务器,读取服务器回写的数据
 *
 * 实现步骤:
 *    创建一个本地字节输入流读取本地的数据源。创建一个客户端socket绑定服务器的ip和端口号。
 *    用socket中方法getOutputStream获取网络字节输出流;输出读取的本地数据到服务端
 *    用socket中方法getInputStream获取网络字节输入流;输入服务端回写的数据
 *    释放资源
 */
public class TCPClient {

    public static void main(String[] args) throws IOException {
        FileInputStream fis=new FileInputStream("D:\\桌面\\发送\\上传图片.jpg");//本地读取文件
        Socket socket=new Socket("127.0.0.1",8889);//创建客户端套接字
        //进行文件上传
        OutputStream os=socket.getOutputStream();
        int len=0;
        byte[]bytes=new byte[1024];
        while ((len=fis.read(bytes))!=-1){
            os.write(bytes,0,len);
        }

        //由于socket的os流的结束标记是读取到-1结束,而while循环又始终不会读取到-1,所以其os流会进入堵塞状态,无法终止
        //因而需要给服务器一个结束的标记;用 socket.shutdownOutput()方法,禁用套接字的os流;
        // 对于TCP套接字,任何以前写入的数据都将被发送,并且后跟TCP的正常终结序列

        socket.shutdownOutput();

        //读取服务端回写数据
        InputStream is=socket.getInputStream();
        while ((len=is.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }

        fis.close();
        socket.close();
    }

}

文件传输案例的优化

在刚才的案例中服务端又以下几个问题:1、仅传输一次服务便终止,无法满足多次传输的;2、接收文件的命名唯一,会造成文件的覆盖问题;3.当多个文件同时上传,服务端一直处于循环状态,会导致效率低下

下面我们将针对这三点进行优化:

第一个问题可以用一个while死循环,让服务端一个保存开启状态;第二个可以设定一个文件命名格式,保证文件名不重复;第三个可以通过多线程的方式解决

优化后Server服务端代码:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Random;

public class TCPServer {

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8888);

        /**
         * 让服务器一直处于监听的状态(死循环accept),同时server.close()也不用在写
         */
        while (true) {
            Socket socket = server.accept();
            /**
             * 使用多线程技术,提高程序的效率
             * 有一个客户端上传文件,就开启一个线程,完成文件的上传
             */
            //完成文件的上传
            new Thread(() -> {
                try {
                    InputStream is = socket.getInputStream();
                    //这个用于在本地盘中创建文件夹来存放图片
                    File file = new File("D:\\桌面\\接收");
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                    //自定义一个文件命名规则,防止同名的文件被覆盖:域名+毫秒值+随机数
                    String fileName = "yz" + System.currentTimeMillis() + new Random().nextInt(10000) + ".jpg";


                    //进行文件的下载(相当于复制)
                    FileOutputStream fos = new FileOutputStream(file + "\\" + fileName);
                    int len = 0;
                    byte[] bytes = new byte[1024];
                    while ((len = is.read(bytes)) != -1) {
                        fos.write(bytes, 0, len);
                    }
                    //回写信息
                    socket.getOutputStream().write("上传成功".getBytes(StandardCharsets.UTF_8));
                    fos.close();
                    socket.close();

                } catch (IOException e) {
                    System.out.println(e);
                }
            }).start();//注意要开启线程,否则线程会一直处于堵塞状态

        }
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值