博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java通过Socket传输文件以及判断文件传输完成的方法
阅读量:4349 次
发布时间:2019-06-07

本文共 16222 字,大约阅读时间需要 54 分钟。

 絮叨

本人学生,往前一年左右的时间用在了Java上

都说写博客、随笔是百利一害的事情-->一害是费时间

近期也是在此申请开通了博客

此篇也算是开博第一篇,所以絮叨一下

——————————————————————————————————————————————————————

问题发现与解决

今天在写Socket的文件传输

程序涉及到Socket、线程、文件操作、流等

目标是Client可以向Server提交文件名

然后Server进行响应-->文件存在则传输,不存在则回复文件不存在的消息

因为想要完成多次文件传输,所以把方法块放进了循环

于是希望所有打开的资源,像InputStream, OutputStream,这些可以再运行过程中一直打开, 直到程序结束才关闭

 

——————————————————————————————————————————————————————

文件传输用的是 DataInputStream 中的 read(byte[] b, int off, int len) 和 DataOutputStream 中的 write(byte[] b, int off, int len)

 

 

 

JavaDoc 地址: 

简单描述

DataInputStream 和 DataOutputStream 是字节流 可以视为-->他们操作的对象是每字节的编码-->机器认识而我不认识的东西

相对应的Writer和Reader 是字符流 他们操作的是将字节编码转化为字符的我能看懂的东西

所以在传输文件的时候使用字节流是更为合适的选择

——————————————————————————————————————————————————————

网上有关文件传输的代码大多是这个样子

通过(FileInputStream) fileInput 从文件读取,并通过(DataOutputStream) out 发送:

1         while((length = fileInput.read(bytes)) != -1) {2             out.write(bytes, 0, length);3             out.flush();4         }

通过(DataInputStream) in 读取数据,并通过(FileOutputStream) fileOutput 写入文件

1         while((length = in.read(bytes, 0, bytes.length)) != -1) {2             fileOutput.write(bytes, 0, length);3             fileOutput.flush();4         }

这两段代码没有问题,都是可以运行的

我的问题出现在接收文件数据的时候,文件数据已经发送完毕,但是程序没有跳出循环

其症结是while()中的判断条件是要 length = -1 才会跳出循环

可以通过上方贴出来的JavaDoc的截图看到-1表示的读取到流的结尾

但是想要让它读取到流的结尾 是要发送方关闭流

在发送方发送完成后需要有类似这样一句 out.close()

执行out.close() 实际上它所包装的socket也随之关闭了

也就是说整条连接都断了 这不是我想要的

我想要的是发送完一个 程序还能够继续响应我从Client发送来的消息

于是需要引入新的判断条件 让接收方知道它想要的文件已经传输完毕

——————————————————————————————————————————————————————

我找到的一个简单的方法是 利用文件的length

传输文件之前,在Server检查文件名是否存在,向Client反馈的时候,将文件的length也发送过去

这样就可在接收文件的时候对本地文件的length和传输过来的length进行比较

从而判断文件传输是否完成

 

1     private static void getBytes(String fileName, long fileLength) throws IOException { 2         File file = new File(fileName); 3         FileOutputStream f = new FileOutputStream(file); 4         byte[] bytes = new byte[1024]; 5         int length = 0; 6         while(true) { 7             length = in.read(bytes, 0, bytes.length); 8             f.write(bytes, 0, length); 9             f.flush();10             /*11              * when fileLength equals to length of local file, it12              * represents the downloading is finished13              */14             if(fileLength == file.length()) break;15         }16         f.close();17     }

 

 

 

 ——————————————————————————————————————————————————————

 

代码

下面是我所写的Socket文件传输的代码

Server

在Server端循环监听绑定端口

在listenRequest()中为每个新连接进来的socket新建一个线程

以此来并发响应每个对应Client的请求

1 import java.io.DataInputStream;  2 import java.io.DataOutputStream;  3 import java.io.File;  4 import java.io.FileInputStream;  5 import java.io.IOException;  6 import java.net.ServerSocket;  7 import java.net.Socket;  8 import java.util.logging.Level;  9 import java.util.logging.Logger; 10  11 public class Server { 12  13      14     private static ServerSocket server; 15     private static Socket socket; 16     private static final int port = 123456; 17     private static Logger logger; 18      19     static{ 20         logger = Logger.getLogger("Server"); 21         logger.setLevel(Level.INFO); 22     } 23      24     public static void main(String[] args) throws IOException { 25         //create server with port 26         server = new ServerSocket(port); 27         logger.info("Server Starts"); 28         while(true) { 29             //listen server and bind socket when accept a connection 30             socket = server.accept(); 31             //record incoming connections 32             logger.info("Get connection from " + socket.getRemoteSocketAddress()); 33             listenRequest(socket); 34         } 35     } 36  37     /** 38      * create a new thread for socket.
39 * listen input from socket
40 * process requests and give responses to client. 41 * @param socket the specific socket that connects to the server 42 */ 43 private static void listenRequest(Socket socket) { 44 /* 45 * create a new thread for this socket so that it 46 * can be responsible for this socket only 47 */ 48 new Thread(new Runnable(){ 49 DataInputStream in; 50 DataOutputStream out; 51 boolean status; 52 53 @Override 54 public void run() { 55 try { 56 logger.info("Start Listening Socket Input"); 57 /* 58 * create DataInputStream and DataOutputStream objects to get 59 * the stream of socket 60 */ 61 in = new DataInputStream(socket.getInputStream()); 62 out = new DataOutputStream(socket.getOutputStream()); 63 status = true; 64 while(status) { 65 processInput(); 66 } 67 } catch (IOException e) { 68 e.printStackTrace(); 69 } 70 } 71 72 /** 73 * process requests from client and give response respectively 74 * @throws IOException 75 */ 76 private void processInput() throws IOException { 77 String content = in.readUTF(); 78 String[] command = content.split(":"); 79 String fileName = null; 80 switch(command[0]) { 81 case "FILE_TRANSFER_REQUEST": 82 /* 83 * structure of FILE_REQUEST should be: 84 * @COMMAND:@FILENAME 85 */ 86 logger.info("Get File Request From " + socket.getRemoteSocketAddress()); 87 fileName = command[1]; 88 fileTransferResponse(fileName); 89 break; 90 case "FILE_BYTES_REQUEST": 91 /* 92 * structure of FILE_BYTES_REQUEST 93 * @Command:@FileName 94 */ 95 fileName = command[1]; 96 logger.info("Get File Bytes Request From " + socket.getRemoteSocketAddress()); 97 fileBytesResponse(fileName); 98 break; 99 case "DISCONNECT":100 logger.info("Get Disconnect From " + socket.getRemoteSocketAddress());101 stop();102 break;103 default:104 break;105 }106 107 }108 109 /**110 * close relevant resources and change status to 111 * false to end this thread112 * @throws IOException113 */114 private void stop() throws IOException {115 in.close();116 out.close();117 socket.close();118 status = false;119 }120 121 /**122 * send file bytes(raw data) to client 123 * @param fileName name of file124 * @throws IOException125 */126 private void fileBytesResponse(String fileName) throws IOException {127 File file = new File(fileName);128 FileInputStream fileInput = new FileInputStream(file);129 byte[] bytes = new byte[1024];130 int length = 0;131 while((length = fileInput.read(bytes)) != -1) {132 out.write(bytes, 0, length);133 out.flush();134 }135 logger.info("File Transfer Finished");136 fileInput.close();137 }138 139 private void fileTransferResponse(String fileName) throws IOException {140 File file = new File(fileName);141 StringBuffer response = new StringBuffer();142 /* 143 * if file does not exist, response to the client144 * with error message145 */146 if(!file.exists()) {147 //make sure there is nothing in response148 response.setLength(0);149 /* 150 * structure of FILE_NOT_EXISTS should be:151 * @COMMAND:@MESSAGE152 */153 response.append("FILE_NOT_EXISTS:");154 response.append("The file \"" + fileName+ "\" your request does not exist.");155 out.writeUTF(response.toString());156 out.flush();157 }else {158 /* 159 * structure of FILE_EXISTS should be;160 * @Command:@FileName:@FileLength161 */162 response.setLength(0);163 response.append("FILE_EXISTS:");164 response.append(fileName+":");165 response.append(file.length());166 out.writeUTF(response.toString());167 out.flush();168 }169 }170 171 }).start();172 }173 174 175 176 }

 

Client

Client中不需要多线程 因此一个主线程完成所有工作

1 import java.io.DataInputStream;  2 import java.io.DataOutputStream;  3 import java.io.File;  4 import java.io.FileOutputStream;  5 import java.io.IOException;  6 import java.io.PrintStream;  7 import java.net.Socket;  8 import java.util.Scanner;  9 import java.util.logging.Level; 10 import java.util.logging.Logger; 11  12 public class Client { 13  14     private static Socket socket; 15     private static final int port = 123456; 16     private static final String host = "***********"; 17     private static Logger logger; 18     private static PrintStream display; 19     private static DataOutputStream out; 20     private static DataInputStream in; 21     private static Scanner sc; 22      23     static{ 24         logger = Logger.getLogger("Client"); 25         logger.setLevel(Level.INFO); 26         display = System.out; 27         sc = new Scanner(System.in); 28     } 29     public static void main(String[] args) { 30         try { 31             /* create a new object of Socket and try to connect to 32              * the server with host and port 33              */ 34             socket = new Socket(host, port); 35              36             //logger.info("Connect to Server "+ host + " with Port "+ port); 37             out = new DataOutputStream(socket.getOutputStream()); 38             in = new DataInputStream(socket.getInputStream()); 39             while(true) { 40                 welcomeInterface(display, sc); 41             } 42         } catch (IOException e) { 43             e.printStackTrace(); 44         } 45     } 46     /** 47      * An interface that instruct users to interact with this program 48      * @param display system out stream 49      * @param sc system input stream 50      * @throws IOException 51      */ 52     private static void welcomeInterface(PrintStream display, Scanner sc) throws IOException { 53         display.println(); 54         for(int i = 0; i < 15; i++) { 55             display.append("#"); 56         } 57         display.append(" Welcome To Week6Client "); 58         for(int i = 0; i < 15; i++) { 59             display.append("#"); 60         } 61         display.println(); 62         display.println(); 63         display.printf("%5s%-30s", " ", "Please Enter The File Name: "); 64         String fileName = sc.nextLine(); 65         display.println(); 66         fileRequest(fileName); 67     } 68  69     /** 70      * send file request to server, and process responses of this request 71      * from server. 72      * @param fileName the name of file that expect to download 73      * @throws IOException 74      */ 75     private static void fileRequest(String fileName) throws IOException { 76         StringBuffer content = new StringBuffer(); 77         /* 78          * structure of FILE_REQUEST: 79          * @command:@fileName 80          */ 81         content.append("FILE_TRANSFER_REQUEST:"); 82         content.append(fileName); 83         out.writeUTF(content.toString()); 84         out.flush(); 85         //logger.info("Send File Request to Server"); 86         // after send request to server, waiting for response from server 87         String[] response = in.readUTF().split(":"); 88         //logger.info("Get Response From Server: " + response[0]); 89         switch(response[0]) { 90         case "FILE_EXISTS": 91             fileName = response[1]; 92             File file = new File(fileName); 93             /* 94              * structure of FILE_EXISTS: 95              * @Command:@FileName:@FileLength 96              */ 97             if(file.exists()) { 98                 display.printf("%5s%s", " ", "File \"" +fileName + "\" exists in current director.\n"); 99                 display.printf("%5s%s", " ", "Do you want to overrid it? \n");100                 display.printf("%5s%s", " ", "Y/y -> Override, Other -> Cancel\n");101                 display.printf("%5s", " ");102                 if(!sc.nextLine().toLowerCase().equals("y")) break;103                 else {104                     file.delete();105                     file.createNewFile();106                 }107             } 108             content.setLength(0);109             content.append("FILE_BYTES_REQUEST:");110             content.append(fileName);111             out.writeUTF(content.toString());112             display.printf("%5s%-30s%s", "",  "Downloading ", fileName+"\n");113             long fileLength = Long.parseLong(response[2]);114             getBytes(fileName, fileLength);115             display.printf("%5s%-20s", "",  "Download Done\n");116             break;117         case "FILE_NOT_EXISTS":118             display.printf("%5s%-50s", "", response[1]);119             break;120             default:121                 break;122         }123         display.println();124         display.printf("%5s%s", " ", "Do you want to continue? \n");125         display.printf("%5s%s", " ", "Y/y -> Continue, Other -> Quit \n");126         display.printf("%5s", "");127         /*128          * if user enter other character, call stop() to close relevant129          * resources and end this process130          */131         if(!sc.nextLine().toLowerCase().equals("y")) {132             display.println();133             display.println();134             stop();135         }136         display.println();137         display.println();138 139     }140 141     /**142      * close relevant resources and call System.exit(int status) to 143      * end this process144      * @throws IOException145      */146     private static void stop() throws IOException {147         out.writeUTF("DISCONNECT");148         out.close();149         in.close();150         sc.close();151         socket.close();152         System.exit(0);153     }154 155     /**156      * Receive bytes from server. Once the length of local file is same157      * as server's, transfer ends.158      * @param fileName the name of file that is going to operate159      * @param fileLength the length of file on server160      * @throws IOException161      */162     private static void getBytes(String fileName, long fileLength) throws IOException {163         File file = new File(fileName);164         FileOutputStream f = new FileOutputStream(file);165         byte[] bytes = new byte[1024];166         int length = 0;167         while(true) {168             length = in.read(bytes, 0, bytes.length);169             f.write(bytes, 0, length);170             f.flush();171             /*172              * when fileLength equals to length of local file, it173              * represents the downloading is finished174              */175             if(fileLength == file.length()) break;176         }177         f.close();178     }179 180 }

 

 

 

 第一次写东西,没什么经验,如有错误、问题请指出

如需讨论 也可发邮件给我哈

email: ancientcoinli@gmail.com

 

 

 

 

 

 

 

——————————————————————————————————————————————————————

 

转载于:https://www.cnblogs.com/ancientcoin/p/10693117.html

你可能感兴趣的文章
linux下使用dd命令写入镜像文件到u盘
查看>>
001---进程
查看>>
视频人脸检测——OpenCV版(三)
查看>>
php获取来访者在搜索引擎搜索某个关键词,进入网站
查看>>
SQL练习之两个列值的交换
查看>>
JavaScript高级程序设计学习笔记--基本概念
查看>>
为 PhpStorm 配置 Xdebug 来调试代码
查看>>
Android 显示确认对话框
查看>>
扩展函数之 IsWhat 简单好用
查看>>
win7下如何建立ftp服务器
查看>>
cocos2dx CCControlButton button大事
查看>>
学习笔记 Android.mk 搜索自己主动
查看>>
linux脚本后台监控执行指定程序的状态(假设程序是死的重新启动程序)
查看>>
从简单的信道预计说起
查看>>
Sublime 脚本 配置 (lua 和 JavaScript篇)
查看>>
Java——XMLl解析
查看>>
关于PHP程序员技术职业生涯规划
查看>>
Redis实战总结-Redis的高可用性
查看>>
修改bin目录下的文件导致session丢失的问题
查看>>
pymysql
查看>>