文件上传分析图解

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

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

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

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

原理:客户端读取本地的文件,把文件上传到服务器,服务器再把上传的文件保存到服务器的硬盘上。

信息回写分析图解

5. 【服务端】获取网络字节缓冲输出流,回写数据。

6. 【客户端】获取网络字节缓冲输入流,解析回写数据。

基本实现步骤

客户端使用本地字节输入流,读取要上传的文件。

客户端使用网络字节输出流,把读取到的文件上传到服务器。

服务器使用网络字节输入流,读取客户端上传的文件。

服务器使用本地字节输出流,把读取到的文件,保存到服务器的硬盘上。

服务器使用网络字节输出流给客户端回写一个"上传成功”。

客户端使用网络字节输入流读取服务器回写的数据。

释放资源。

服务端实现

读取客户端上传的文件,保存到服务器的硬盘,给客户端回写"上传成功"。

保存目的地:

"/Users/liyihua/IdeaProjects/Study/src/view/study/demo38/CopyFile.jpg"

实现代码:

importjava.io.BufferedInputStream;importjava.io.BufferedOutputStream;importjava.io.FileOutputStream;importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;public classTcpFileUploadServer {public static void main(String[] args) throwsIOException {

System.out.println("服务器启动时间:" +System.currentTimeMillis());

method();

System.out.println("服务器关闭时间:" +System.currentTimeMillis());

}private static void method() throwsIOException {//1. 创建服务端ServerSocket

ServerSocket serverSocket = new ServerSocket(8888);//2. 建立连接

Socket accept =serverSocket.accept();//3. 创建流对象//3.1 获取网络字节缓冲输入流,读取文件数据

BufferedInputStream bis1 = newBufferedInputStream(accept.getInputStream());//3.2 创建本地字节缓冲输出流,保存到本地

BufferedOutputStream bos1 = new BufferedOutputStream(new FileOutputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo38/CopyFile.jpg"));//4. 读写上传文件的数据

byte[] b = new byte[1024];intlen;while ((len = bis1.read(b)) != -1) {

bos1.write(b,0, len);

}//5. 上传成功//5.1 服务端,创建网络字节缓冲输出流

BufferedOutputStream bos2 = newBufferedOutputStream(accept.getOutputStream());//5.2 给客户回写数据:"上传成功"。

bos2.write("上传成功".getBytes());//5. 释放资源

bos1.close();

bis1.close();

bos2.close();

accept.close();

}

}

客户端实现

读取本地文件,上传到服务器,读取服务器回写的数据。

本地文件地址:

"/Users/liyihua/IdeaProjects/Study/src/view/study/demo38/LocalFile.jpg"

实现代码:

importjava.io.BufferedInputStream;importjava.io.BufferedOutputStream;importjava.io.FileInputStream;importjava.io.IOException;importjava.net.Socket;public classTcpFileUploadClient {public static void main(String[] args) throwsIOException {

System.out.println("客户端启动时间:" +System.currentTimeMillis());

method();

System.out.println("客户端关闭时间:" +System.currentTimeMillis());

}private static void method() throwsIOException {//1. 创建流对象//1.1 创建本地字节缓冲输入流,读取本地文件

BufferedInputStream bis1 = new BufferedInputStream(new FileInputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo38/LocalFile.jpg"));//1.2 创建网络字节缓冲输出流,写到服务端

Socket socket = new Socket("localhost", 8888);

BufferedOutputStream bos1= newBufferedOutputStream(socket.getOutputStream());//2. 写出本地文件数据

byte[] bytes1 = new byte[1024];intlen1;while (( len1 = bis1.read(bytes1)) != -1) {

bos1.write(bytes1,0, len1);

bos1.flush();

}//3. 上传成功//3.1 客户端,创建网络字节缓冲输入流

BufferedInputStream bis2 = newBufferedInputStream(socket.getInputStream());//3.2 读取服务器回写的数据

byte[] bytes2 = new byte[1024];intlen2;while (( len2 = bis2.read(bytes2)) != -1) {

bos1.write(bytes2,0, len2);

bos1.flush();

}//3. 释放资源

bos1.close();

socket.close();

bis1.close();

}

}

程序运行

文件上传优化分析

文件名称写死问题

服务端,保存文件的名称如果写死,那么最终导致服务器硬盘,只会保留一个文件,建议使用系统时间优化,保证文件名称唯一,代码如下:

FileOutputStream fis = new FileOutputStream(System.currentTimeMillis()+".jpg"); //文件名称

BufferedOutputStream bos = new BufferedOutputStream(fis);

循环接收的问题

服务端,只保存一个文件就关闭了,之后的用户无法再上传,这是不符合实际的,使用循环改进,可以不断的接收不同用户的文件,代码如下:

//每次接收新的连接,创建一个Socket

while(true){

Socket accept=serverSocket.accept();

......

}

效率问题

服务端,在接收大文件时,可能耗费几秒钟的时间,此时不能接收其他用户上传,所以,使用多线程技术优化,代码如下:

while (true) {

Socket accept=serverSocket.accept();//accept交给子线程处理

new Thread(newRunnable() {

@Overridepublic voidrun() {

......

BufferedInputStream bis= newBufferedInputStream(accept.getInputStream());

......

}

}).start();

}

这里使用了匿名内部类实现Runnable接口,由于该接口中只有一个抽象方法,所以也可以使用Lambda表达式来简化代码:

while (true) {

Socket accept=serverSocket.accept();//accept交给子线程处理

newThread(

()->{

......

BufferedInputStream bis= newBufferedInputStream(accept.getInputStream());

......

}

).start();

}

优化实现

importjava.io.BufferedInputStream;importjava.io.BufferedOutputStream;importjava.io.FileOutputStream;importjava.io.IOException;importjava.net.ServerSocket;importjava.net.Socket;public classTcp01FileUploadServer {public static void main(String[] args) throwsIOException {

System.out.println("服务器启动时间:" +System.currentTimeMillis());

method();

System.out.println("服务器关闭时间:" +System.currentTimeMillis());

}private static void method() throwsIOException {//1. 创建服务端ServerSocket

ServerSocket serverSocket = new ServerSocket(8888);//2. 循环接收,建立连接

while (true) {//2.1 建立连接

Socket accept =serverSocket.accept();newThread(

()->{try(//3. 创建流对象//3.1 获取网络字节缓冲输入流,读取文件数据

BufferedInputStream bis1 = newBufferedInputStream(accept.getInputStream());//3.2 创建本地字节缓冲输出流,保存到本地

BufferedOutputStream bos1 = new BufferedOutputStream(new FileOutputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo38/CopyFile.jpg"));//4. 上传成功//4.1 服务端,创建网络字节缓冲输出流

BufferedOutputStream bos2 = newBufferedOutputStream(accept.getOutputStream());

) {//5. 读写上传文件的数据

byte[] b = new byte[1024];intlen;while ((len = bis1.read(b)) != -1) {

bos1.write(b,0, len);

}

bos1.flush();//6. 给客户回写数据:"上传成功"。

bos2.write("上传成功".getBytes());

bos2.flush();//7. 释放资源

bos1.close();

bis1.close();

bos2.close();

accept.close();

}catch(IOException e) {

e.printStackTrace();

}

}

).start();

}

}

}

这里虽然实现了多个文件同时上传,不过会在内存中不断的创建线程和销毁线程,造成效率低下,浪费内存资源。线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。 说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。

TCP文件上传Java_Java 理解TCP通信案例:文件上传案例相关推荐

  1. excel上传java_java:Excel操作之Excel上传

    1.导入我们需要的jar包. 2.创建servlet命名为UploadExcelServlet,url为UploadExcelServlet. 3.创建Excel的批量处理方法ExcelBatchUt ...

  2. TCP文件上传Java_java 基于TCP协议的文件上传

    参考文档 1.https://www.sxt.cn/Java_jQuery_in_action/ten-filebytestream.html 2.https://www.sxt.cn/Java_jQ ...

  3. 计算机tcp端口有几个,理解 TCP(一):端口

    端口与进程 TCP 的包是不包含 IP 地址信息的,那是 IP 层上的事,但是有源端口和目的端口. 就是说,端口这一东西,是属于 TCP 知识范畴的. 我们知道两个进程,在计算机内部进行通信,可以有管 ...

  4. oracle通信通道的文件结尾_Oracle错误——ORA-03113:在通信信道文件的末尾 解决方案...

    起源 今天跟往常一样,登陆PL/SQL,确登陆失败,出现一个错误"ORA-01034"和"ORA-27101"如图: 然后就就通过命令提示符去登陆Oracle, ...

  5. linux shell 执行多个文件,/etc/profile、~/.bash_profile等几个文件的执行过程

    关于登录linux时,/etc/profile.~/.bash_profile等几个文件的执行过程. 在登录Linux时要执行文件的过程如下: 在 刚登录Linux时,首先启动 /etc/profil ...

  6. JAVA客户端数据传输_java模拟TCP通信实现客户端上传文件到服务器端

    java模拟TCP通信实现客户端上传文件到服务器端,供大家参考,具体内容如下 客户端 package com.zr; import java.io.FileInputStream; import ja ...

  7. Python3之socket编程(TCP/UDP,粘包问题,数据传输、文件上传)

    一.socket的定义 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后 ...

  8. [通俗易懂]深入理解TCP协议(上):理论基础

    转自即时通讯网:http://www.52im.net/ 前言 TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的 ...

  9. tcp当主动发出syn_(二)深入浅出TCPIP之再识TCP,理解TCP三次握手(上)

    TCP作为一种可靠传输控制协议,其核心思想:既要保证数据可靠传输,又要提高传输的效率,而用三次握手恰恰可以满足以上两方面的需求! 1.三次握手 所谓的三次握手即TCP连接的建立.这个连接必须是一方主动 ...

最新文章

  1. 如何零门槛搭建实时音视频通信平台
  2. PyCharm 2020.1 稳定版发布
  3. iOS设计模式 - 迭代器
  4. 一个比较简单驱动程序[编译环境]
  5. Smokeping的参数使用说明
  6. php函数积累第二弹(关于文件操作)
  7. 【算法】剑指 Offer 18. 删除链表的节点
  8. thinkphp v5.0.11漏洞_Thinkphp 5.0远程代码执行漏洞
  9. Unable to add window -- token android.os.BinderProxy---Android原生开发工作笔记142
  10. ORACLE 两个表或两个结果集的数据对比常用的函数
  11. dBm和dB(纯计数单位)
  12. java 代码块 构造函数_Java学习笔记之------构造函数,静态关键字,静态代码块,构造代...
  13. [Git] 009 逆转未来
  14. 插入法排序(c语言)
  15. 沃森计算机显能耐,微型气象预报有戏
  16. 青蛙跳台阶变态青蛙跳台阶
  17. html----烟花代码
  18. linux deploy镜像容量扩容
  19. 汽车厂商对高通骁龙820A系统平台的支持
  20. ARDUINO传感器专题介绍(2)

热门文章

  1. 图解分析:基于setnx的分布式锁有什么缺陷
  2. c语言模拟计算机程序阶乘,辽宁省计算机二级(C语言)模拟试卷B(无答案).doc
  3. vue自定义组件递归实现树状_一道价值25k的腾讯递归组件面试题(Vue3 + TS 实现)...
  4. python面向对象编程指南 豆瓣_一文看懂Python面向对象编程(Python学习与新手入门必看)-绝对原创...
  5. 又涨啦!2021年6月程序员工资出炉
  6. 制备石墨烯流程图_科研人员制备出小扭转角度双层石墨烯
  7. linux java mysql 备份 runtime_Mysql如何在linux中实现定时备份
  8. Access在Win10连接失败的问题
  9. Python Imaging Library: ImageEnhance Module(图像增强模块)
  10. 宝塔面板 php关闭拓展,宝塔Linux面板中PHP如何安装扩展及禁用函数?