• Java 网络编程案例三:多个客户端上传文件


      需求:每一个客户端启动后都可以给服务器上传一个文件,服务器接收到文件后保存到一个upload目录中。可以同时接收多个客户端的文件上传。

      分析:

      (1)服务器端要“同时”处理多个客户端的请求,那么必须使用多线程,每一个客户端的通信需要单独的线程来处理。

      (2)服务器保存上传文件的目录只有一个upload,而每个客户端给服务器发送的文件可能重名,所以需要保证文件名的唯一。我们可以使用“时间戳”作为文件名,而后缀名不变

      (3)客户端需要给服务器上传文件名(含后缀名)以及文件内容。而文件名是字符串,文件内容不一定是纯文本的,因此选择DataOutputStream和DataInputStream。

      客户端的实例代码:

     1 import java.io.BufferedReader;
     2 import java.io.DataOutputStream;
     3 import java.io.File;
     4 import java.io.FileInputStream;
     5 import java.io.InputStream;
     6 import java.io.InputStreamReader;
     7 import java.io.OutputStream;
     8 import java.net.Socket;
     9 import java.util.Scanner;
    10 
    11 public class Client {
    12     public static void main(String[] args) throws Exception {
    13         // (1)连接服务器
    14         Socket socket = new Socket("192.168.54.68", 8888);
    15 
    16         Scanner input = new Scanner(System.in);
    17         
    18         //(2)从键盘输入文件的路径和名称
    19         System.out.print("请选择要上传的文件:");
    20         String path = input.nextLine();
    21         File file = new File(path);
    22         
    23         OutputStream out = socket.getOutputStream();
    24         DataOutputStream dos = new DataOutputStream(out);//用它的目的是为了既可以单独传一个字符串,又可以写字节内容
    25         
    26         //先发送文件名(含后缀名)
    27         dos.writeUTF(file.getName());//单独发一个字符串
    28         
    29         //还需要一个IO流,从文件读取内容,给服务器发过去
    30         FileInputStream fis = new FileInputStream(file);
    31                 
    32         //(3)把文件内容给服务器传过去,类似与复制文件
    33         byte[] data = new byte[1024];
    34         while(true){
    35             int len = fis.read(data);
    36             if(len==-1){
    37                 break;
    38             }
    39             dos.write(data, 0, len);
    40         }
    41         socket.shutdownOutput();
    42         
    43         //(4)接收服务器返回的结果
    44         InputStream is = socket.getInputStream();
    45         InputStreamReader isr = new InputStreamReader(is);//把字节流转成字符流
    46         BufferedReader br = new BufferedReader(isr);
    47         String result = br.readLine();
    48         System.out.println(result);
    49         
    50         //(5)关闭
    51         fis.close();
    52         input.close();
    53         socket.close();
    54     }
    55 }

      服务器端的示例代码:

     1 import java.net.ServerSocket;
     2 import java.net.Socket;
     3 
     4 public class Server {
     5     public static void main(String[] args) throws Exception{
     6         //服务器在8888端口号监听数据
     7         @SuppressWarnings("resource")
     8         ServerSocket server = new ServerSocket(8888);
     9         
    10         while(true){
    11             //(2)等待连接 
    12             //这句代码执行一次,意味着一个客户端连接
    13             Socket accept = server.accept();
    14         
    15             FileUploadThread ft = new FileUploadThread(accept);
    16             ft.start();
    17         }
    18     }
    19 }

      服务器端处理每一个客户端上传文件的线程类代码:

     1 import java.io.DataInputStream;
     2 import java.io.FileNotFoundException;
     3 import java.io.FileOutputStream;
     4 import java.io.IOException;
     5 import java.io.InputStream;
     6 import java.io.OutputStream;
     7 import java.io.PrintStream;
     8 import java.net.Socket;
     9 import java.text.SimpleDateFormat;
    10 import java.util.Date;
    11 
    12 public class FileUploadThread extends Thread{
    13     private Socket socket;
    14     private String dir = "upload/";
    15 
    16     public FileUploadThread(Socket socket) {
    17         super();
    18         this.socket = socket;
    19     }
    20     
    21     public void run(){
    22         FileOutputStream fos = null;
    23         try {
    24             InputStream is = socket.getInputStream();
    25             DataInputStream dis = new DataInputStream(is);    
    26             
    27             //读取文件名(含后缀名)
    28             String filename = dis.readUTF();
    29             //截取后缀名
    30             String ext = filename.substring(filename.lastIndexOf("."));
    31             //生成时间戳
    32             SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    33             filename = sf.format(new Date());
    34             //用新文件路径构建文件输出流
    35             fos = new FileOutputStream(dir + filename + ext);
    36             //接收文件内容
    37             byte[] data = new byte[1024];
    38             while(true){
    39                 int len = is.read(data);
    40                 if(len==-1){
    41                     break;
    42                 }
    43                 fos.write(data, 0, len);
    44             }
    45             
    46             //返回结果
    47             OutputStream out = socket.getOutputStream();
    48             PrintStream ps = new PrintStream(out);
    49             ps.println(filename + ext + ":已上传完毕");
    50         } catch (FileNotFoundException e) {
    51             e.printStackTrace();
    52         } catch (IOException e) {
    53             e.printStackTrace();
    54         }finally{
    55             try {
    56                 fos.close();
    57                 socket.close();
    58             } catch (IOException e) {
    59                 e.printStackTrace();
    60             }
    61         }
    62     }
    63 }
  • 相关阅读:
    综合:bool类型 命名空间 输入输出
    C++命名空间
    C++输入输出
    C++新特性
    C++ IDE环境
    C++简介
    3 python3 编码解码问题 upd接受数据
    2 socket UDP通信
    1 网络基础知识
    15 GIL 全局解释器锁 C语言解决 top ps
  • 原文地址:https://www.cnblogs.com/niujifei/p/12291766.html
Copyright © 2020-2023  润新知