11.3 综合案例
11.3.1 文件上传案例
文件上传分析图解
【客户端】输入流,从硬盘读取文件数据到程序中。
【客户端】输出流,写出文件数据到服务端。
【服务端】输入流,读取文件数据到服务端程序。
【服务端】输出流,写出文件数据到服务器硬盘中。

基本实现
服务端实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class FileUpload_Server { public static void main(String[] args) throws IOException { System.out.println("服务器 启动..... "); ServerSocket serverSocket = new ServerSocket(6666); Socket accept = serverSocket.accept(); BufferedInputStream bis = new BufferedInputStream(accept.getInputStream()); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg)")); byte[] b = new byte[1024 * 8]; int len; while ((len = bis.read(b)) != ‐1) { bos.write(b, 0, len); } bos.close(); bis.close(); accept.close(); System.out.println("文件上传已保存"); } }
|
客户端实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class FileUPload_Client { public static void main(String[] args) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg)")); Socket socket = new Socket("localhost", 6666); BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); byte[] b = new byte[1024 * 8 ]; int len ; while (( len = bis.read(b))!=‐1) { bos.write(b, 0, len); bos.flush(); } System.out.println("文件发送完毕"); bos.close(); socket.close(); bis.close(); System.out.println("文件上传完毕 "); } }
|
文件上传优化分析
文件名称写死的问题
服务端,保存文件的名称如果写死,那么最终导致服务器硬盘,只会保留一个文件,建议使用系统时间优化,保证文件名称唯一,代码如下:
1 2
| FileOutputStream fis = new FileOutputStream(System.currentTimeMillis()+".jpg)") BufferedOutputStream bos = new BufferedOutputStream(fis);
|
循环接收的问题
服务端,指保存一个文件就关闭了,之后的用户无法再上传,这是不符合实际的,使用循环改进,可以不断的接收不同用户的文件,代码如下:
1 2 3 4 5
| while(true){ Socket accept = serverSocket.accept(); ...... }
|
效率问题
服务端,在接收大文件时,可能耗费几秒钟的时间,此时不能接收其他用户上传,所以,使用多线程技术优化,代码如下:
1 2 3 4 5 6 7 8 9
| while(true){ Socket accept = serverSocket.accept(); new Thread(() ‐> { ...... InputStream bis = accept.getInputStream(); ...... }).start(); }
|
优化实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class FileUpload_Server { public static void main(String[] args) throws IOException { System.out.println("服务器 启动..... "); ServerSocket serverSocket = new ServerSocket(6666); while (true) { Socket accept = serverSocket.accept();
new Thread(() ‐> { try ( BufferedInputStream bis = new BufferedInputStream(accept.getInputStream()); FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg)"); BufferedOutputStream bos = new BufferedOutputStream(fis);) { byte[] b = new byte[1024 * 8]; int len; while ((len = bis.read(b)) != ‐1) { bos.write(b, 0, len); } bos.close(); bis.close(); accept.close(); System.out.println("文件上传已保存"); } catch (IOException e) { e.printStackTrace(); } }).start(); } } }
|
信息回写分析图解
前四步与基本文件上传一致.
【服务端】获取输出流,回写数据。
【客户端】获取输入流,解析回写数据。

回写实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class FileUpload_Server { public static void main(String[] args) throws IOException { System.out.println("服务器 启动..... "); ServerSocket serverSocket = new ServerSocket(6666); while (true) { Socket accept = serverSocket.accept();
new Thread(() ‐> { try ( BufferedInputStream bis = new BufferedInputStream(accept.getInputStream()); FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg)"); BufferedOutputStream bos = new BufferedOutputStream(fis); ) { byte[] b = new byte[1024 * 8]; int len; while ((len = bis.read(b)) != ‐1) { bos.write(b, 0, len); } System.out.println("back ........"); OutputStream out = accept.getOutputStream(); out.write("上传成功".getBytes()); out.close(); bos.close(); bis.close(); accept.close(); System.out.println("文件上传已保存"); } catch (IOException e) { e.printStackTrace(); } }).start(); } } }
|
客户端实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class FileUpload_Client { public static void main(String[] args) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg)")); Socket socket = new Socket("localhost", 6666); BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); byte[] b = new byte[1024 * 8 ]; int len ; while (( len = bis.read(b))!=‐1) { bos.write(b, 0, len); } socket.shutdownOutput(); System.out.println("文件发送完毕"); InputStream in = socket.getInputStream(); byte[] back = new byte[20]; in.read(back); System.out.println(new String(back)); in.close(); socket.close(); bis.close(); } }
|
11.3.2 模拟B\S服务器
模拟网站服务器,使用浏览器访问自己编写的服务端程序,查看网页效果。
案例分析
准备页面数据,web文件夹。
复制到我们Module中,比如复制到day08中

我们模拟服务器端,ServerSocket类监听端口,使用浏览器访问
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(8000); Socket socket = server.accept(); InputStream in = socket.getInputStream(); byte[] bytes = new byte[1024]; int len = in.read(bytes); System.out.println(new String(bytes,0,len)); socket.close(); server.close(); }
|

服务器程序中字节输入流可以读取到浏览器发来的请求信息

GET/web/index.html HTTP/1.1是浏览器的请求消息。/web/index.html为浏览器想要请求的服务器端的资源,使用字符串切割方式获取到请求的资源。
1 2 3 4 5 6 7 8
| BufferedReader readWb = new BufferedReader(new InputStreamReader(socket.getInputStream())); String requst = readWb.readLine();
String[] strArr = requst.split(" ");
String path = strArr[1].substring(1); System.out.println(path);
|
案例实现
服务端实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class SerDemo { public static void main(String[] args) throws IOException { System.out.println("服务端 启动 , 等待连接 .... "); ServerSocket server = new ServerSocket(8888); Socket socket = server.accept(); BufferedReader readWb = new BufferedReader(new InputStreamReader(socket.getInputStream())); String requst = readWb.readLine(); String[] strArr = requst.split(" "); String path = strArr[1].substring(1); FileInputStream fis = new FileInputStream(path); byte[] bytes= new byte[1024]; int len = 0 ; OutputStream out = socket.getOutputStream(); out.write("HTTP/1.1 200 OK\r\n".getBytes()); out.write("Content‐Type:text/html\r\n".getBytes()); out.write("\r\n".getBytes()); while((len = fis.read(bytes))!=‐1){ out.write(bytes,0,len); } fis.close(); out.close(); readWb.close(); socket.close(); server.close(); } }
|
访问效果
火狐

小贴士:
不同的浏览器,内核不一样,解析效果有可能不一样。
发现浏览器中出现很多的叉子,说明浏览器没有读取到图片信息导致。
浏览器工作原理是遇到图片会开启一个线程进行单独的访问,因此在服务器端加入线程技术。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public class ServerDemo { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(8888); while(true){ Socket socket = server.accept(); new Thread(new Web(socket)).start(); } } static class Web implements Runnable{ private Socket socket; public Web(Socket socket){ this.socket=socket; } public void run() { try{ BufferedReader readWb = new BufferedReader(new InputStreamReader(socket.getInputStream())); String requst = readWb.readLine(); String[] strArr = requst.split(" "); System.out.println(Arrays.toString(strArr)); String path = strArr[1].substring(1); System.out.println(path); FileInputStream fis = new FileInputStream(path); System.out.println(fis); byte[] bytes= new byte[1024]; int len = 0 ; OutputStream out = socket.getOutputStream(); out.write("HTTP/1.1 200 OK\r\n".getBytes()); out.write("Content‐Type:text/html\r\n".getBytes()); out.write("\r\n".getBytes()); while((len = fis.read(bytes))!=‐1){ out.write(bytes,0,len); } fis.close(); out.close(); readWb.close(); socket.close(); }catch(Exception ex){ } } } }
|
访问效果:

图解:

本文标题:第三部分 第十一章 3.综合案例
文章作者:foreverSFJ
发布时间:2019-08-21 10:04:39
最后更新:2019-08-21 10:04:39
原始链接:Notes/Java/Basic/Part03/11_3 综合案例.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明出处!