day11【网络编程】
主要内容
- 软件架构CS/BS
- 网络通信三要素
- TCP通信
- Socket套接字
- ServerSocket
教学目标
-
[ ]
能够辨别UDP和TCP协议特点
-
[ ]
能够说出TCP协议下两个常用类名称
-
[ ]
能够编写TCP协议下字符串数据传输程序
-
[ ]
能够理解TCP协议下文件上传案例
-
[ ]
能够理解TCP协议下案例2
第一章 网络编程入门
1.1软件结构
- C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件。
[图片上传失败...(image-e6d2b0-1580309731417)]
B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等。
[图片上传失败...(image-d9f3df-1580309731417)]
两种架构各有优势,但是无论哪种架构,都离不开网络的支持。网络编程,就是在一定的协议下,实现两台计算机的通信的程序。
1.2 网络通信协议
网络通信协议:通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。
TCP/IP协议: 传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议。它定义了计算机如何连入因特网,以及数据如何在它们之间传输的标准。它的内部包含一系列的用于处理数据通信的协议,并采用了4层的分层模型,每一层都呼叫它的下一层所提供的协议来完成自己的需求。
[图片上传失败...(image-a0627b-1580309731416)]
上图中,TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层,每层分别负责不同的通信功能。 链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。 运输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。
1.3 协议分类
通信的协议还是比较复杂的,java.net
包中包含的类和接口,它们提供低层次的通信细节。我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。
java.net
包中提供了两种常见的网络协议的支持:
-
UDP:用户数据报协议(User Datagram Protocol)。UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。UDP的交换过程如下图所示。
[图片上传失败...(image-59ef04-1580309731416)]
特点:数据被限制在64kb以内,超出这个范围就不能发送了。
数据报(Datagram):网络传输的基本单位
-
TCP:传输控制协议 (Transmission Control Protocol)。TCP协议是面向连接的通信协议,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过“三次握手”。
-
三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。
- 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
- 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
- 第三次握手,客户端再次向服务器端发送确认信息,确认连接。整个交互过程如下图所示。
-
[图片上传失败...(image-b55da1-1580309731415)]
完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输了。由于这种面向连接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛,例如下载文件、浏览网页等。
1.4 网络编程三要素
协议
- 协议:计算机网络通信必须遵守的规则,已经介绍过了,不再赘述。
IP地址
- IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。IP地址用来给一个网络中的计算机设备做唯一的编号。假如我们把“个人电脑”比作“一台电话”的话,那么“IP地址”就相当于“电话号码”。
IP地址分类
IPv4:是一个32位的二进制数,通常被分为4个字节,表示成
a.b.c.d
的形式,例如192.168.65.100
。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。-
IPv6:由于互联网的蓬勃发展,IP地址的需求量愈来愈大,但是网络地址资源有限,使得IP的分配越发紧张。
为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成
ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
,号称可以为全世界的每一粒沙子编上一个网址,这样就解决了网络地址资源数量不够的问题。
常用命令
- 查看本机IP地址,在控制台输入:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="385" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="248" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="403">ipconfig</pre>
</pre>
- 检查网络是否连通,在控制台输入:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="408" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="249" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="426">ping 空格 IP地址</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="431">ping 220.181.57.216</pre>
</pre>
特殊的IP地址
- 本机IP地址:
127.0.0.1
、localhost
。
端口号
网络的通信,本质上是两个进程(应用程序)的通信。每台计算机都有很多的进程,那么在网络通信时,如何区分这些进程呢?
如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了。
- 端口号:用两个字节表示的整数,它的取值范围是0~65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。
利用协议
+IP地址
+端口号
三元组合,就可以标识网络中的进程了,那么进程间的通信就可以利用这个标识与其它进程进行交互。
第二章 TCP通信程序
2.1 概述
TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。
两端通信时步骤:
- 服务端程序,需要事先启动,等待客户端的连接。
- 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。
在Java中,提供了两个类用于实现TCP通信程序:
- 客户端:
java.net.Socket
类表示。创建Socket
对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。 - 服务端:
java.net.ServerSocket
类表示。创建ServerSocket
对象,相当于开启一个服务,并等待客户端的连接。
2.2 Socket类
Socket
类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。
构造方法
-
public Socket(String host, int port)
:创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null ,则相当于指定地址为回送地址。小贴士:回送地址(127.x.x.x) 是本机回送地址(Loopback Address),主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,立即返回,不进行任何网络传输。
构造举例,代码如下:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="501" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="250" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="519">Socket client = new Socket("127.0.0.1", 6666);</pre>
</pre>
成员方法
-
public InputStream getInputStream()
: 返回此套接字的输入流。- 如果此Scoket具有相关联的通道,则生成的InputStream 的所有操作也关联该通道。
- 关闭生成的InputStream也将关闭相关的Socket。
-
public OutputStream getOutputStream()
: 返回此套接字的输出流。- 如果此Scoket具有相关联的通道,则生成的OutputStream 的所有操作也关联该通道。
- 关闭生成的OutputStream也将关闭相关的Socket。
-
public void close()
:关闭此套接字。- 一旦一个socket被关闭,它不可再使用。
- 关闭此socket也将关闭相关的InputStream和OutputStream 。
-
public void shutdownOutput()
: 禁用此套接字的输出流。- 任何先前写出的数据将被发送,随后终止输出流。
2.3 ServerSocket类
ServerSocket
类:这个类实现了服务器套接字,该对象等待通过网络的请求。
构造方法
-
public ServerSocket(int port)
:使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号。
构造举例,代码如下:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="558" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="251" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="576">ServerSocket server = new ServerSocket(6666);</pre>
</pre>
成员方法
-
public Socket accept()
:侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接。
2.4 简单的TCP网络程序
TCP通信分析图解
- 【服务端】启动,创建ServerSocket对象,等待连接。
- 【客户端】启动,创建Socket对象,请求连接。
- 【服务端】接收连接,调用accept方法,并返回一个Socket对象。
- 【客户端】Socket对象,获取OutputStream,向服务端写出数据。
- 【服务端】Scoket对象,获取InputStream,读取客户端发送的数据。
到此,客户端向服务端发送数据成功。
[图片上传失败...(image-9ac6f2-1580309731413)]
自此,服务端向客户端回写数据。
- 【服务端】Socket对象,获取OutputStream,向客户端回写数据。
- 【客户端】Scoket对象,获取InputStream,解析回写数据。
- 【客户端】释放资源,断开连接。
客户端向服务器发送数据
服务端实现:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="614" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="252" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="632">public class ServerTCP {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="637"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="647"> System.out.println("服务端启动 , 等待连接 .... ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="653"> // 1.创建 ServerSocket对象,绑定端口,开始等待连接</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="656"> ServerSocket ss = new ServerSocket(6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="664"> // 2.接收连接 accept 方法, 返回 socket 对象.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="667"> Socket server = ss.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="674"> // 3.通过socket 获取输入流</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="677"> InputStream is = server.getInputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="684"> // 4.一次性读取数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="687"> // 4.1 创建字节数组</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="691"> byte[] b = new byte[1024];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="699"> // 4.2 据读取到字节数组中.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="703"> int len = is.read(b);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="712"> // 4.3 解析数组,打印字符串信息</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="715"> String msg = new String(b, 0, len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="725"> System.out.println(msg);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="731"> //5.关闭资源.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="734"> is.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="738"> server.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="742"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="744">}</pre>
</pre>
客户端实现:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="749" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="253" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="767">public class ClientTCP {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="772"> public static void main(String[] args) throws Exception {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="783"> System.out.println("客户端 发送数据");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="791"> // 1.创建 Socket ( ip , port ) , 确定连接到哪里.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="796"> Socket client = new Socket("localhost", 6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="807"> // 2.获取流对象 . 输出流</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="812"> OutputStream os = client.getOutputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="821"> // 3.写出数据.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="826"> os.write("你好么? tcp ,我来了".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="834"> // 4. 关闭资源 .</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="839"> os.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="845"> client.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="851"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="854">}</pre>
</pre>
服务器向客户端回写数据
服务端实现:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="862" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="254" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="880">public class ServerTCP {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="885"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="895"> System.out.println("服务端启动 , 等待连接 .... ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="901"> // 1.创建 ServerSocket对象,绑定端口,开始等待连接</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="904"> ServerSocket ss = new ServerSocket(6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="912"> // 2.接收连接 accept 方法, 返回 socket 对象.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="915"> Socket server = ss.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="922"> // 3.通过socket 获取输入流</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="925"> InputStream is = server.getInputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="932"> // 4.一次性读取数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="935"> // 4.1 创建字节数组</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="939"> byte[] b = new byte[1024];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="947"> // 4.2 据读取到字节数组中.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="951"> int len = is.read(b);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="960"> // 4.3 解析数组,打印字符串信息</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="963"> String msg = new String(b, 0, len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="973"> System.out.println(msg);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="979"> // =================回写数据=======================</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="983"> // 5. 通过 socket 获取输出流</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="987"> OutputStream out = server.getOutputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="995"> // 6. 回写数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="999"> out.write("我很好,谢谢你".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1006"> // 7.关闭资源.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1010"> out.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1015"> is.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1019"> server.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1023"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1025">}</pre>
</pre>
客户端实现:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="1030" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="255" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1048">public class ClientTCP {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1053"> public static void main(String[] args) throws Exception {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1064"> System.out.println("客户端 发送数据");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1072"> // 1.创建 Socket ( ip , port ) , 确定连接到哪里.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1077"> Socket client = new Socket("localhost", 6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1088"> // 2.通过Scoket,获取输出流对象 </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1093"> OutputStream os = client.getOutputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1102"> // 3.写出数据.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1107"> os.write("你好么? tcp ,我来了".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1115"> // ==============解析回写=========================</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1119"> // 4. 通过Scoket,获取 输入流对象</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1123"> InputStream in = client.getInputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1131"> // 5. 读取数据数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1135"> byte[] b = new byte[100];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1144"> int len = in.read(b);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1153"> System.out.println(new String(b, 0, len));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1164"> // 6. 关闭资源 .</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1169"> in.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1174"> os.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1180"> client.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1186"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1189">}</pre>
</pre>
第三章 综合案例
3.1 文件上传案例
文件上传分析图解
- 【客户端】输入流,从硬盘读取文件数据到程序中。
- 【客户端】输出流,写出文件数据到服务端。
- 【服务端】输入流,读取文件数据到服务端程序。
- 【服务端】输出流,写出文件数据到服务器硬盘中。
[图片上传失败...(image-c2f160-1580309731412)]
基本实现
服务端实现:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="1211" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="256" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1229">public class FileUpload_Server {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1234"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1244"> System.out.println("服务器 启动..... ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1250"> // 1. 创建服务端ServerSocket</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1253"> ServerSocket serverSocket = new ServerSocket(6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1262"> // 2. 建立连接 </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1267"> Socket accept = serverSocket.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1274"> // 3. 创建流对象</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1278"> // 3.1 获取输入流,读取文件数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1282"> BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1291"> // 3.2 创建输出流,保存到本地 .</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1294"> BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1304"> // 4. 读写数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1309"> byte[] b = new byte[1024 * 8];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1319"> int len;</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1323"> while ((len = bis.read(b)) != -1) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1334"> bos.write(b, 0, len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1341"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1343"> //5. 关闭 资源</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1346"> bos.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1350"> bis.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1354"> accept.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1358"> System.out.println("文件上传已保存");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1364"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1366">}</pre>
</pre>
客户端实现:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="1371" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="257" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1389">public class FileUPload_Client {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1394"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1405"> // 1.创建流对象</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1408"> // 1.1 创建输入流,读取本地文件</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1411"> BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg"));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1421"> // 1.2 创建输出流,写到服务端 </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1424"> Socket socket = new Socket("localhost", 6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1433"> BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1442"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1445"> //2.写出数据. </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1448"> byte[] b = new byte[1024 * 8 ];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1458"> int len ; </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1462"> while (( len = bis.read(b))!=-1) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1472"> bos.write(b, 0, len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1479"> bos.flush();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1483"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1485"> System.out.println("文件发送完毕");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1491"> // 3.释放资源</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1494"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1497"> bos.close(); </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1501"> socket.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1505"> bis.close(); </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1509"> System.out.println("文件上传完毕 ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1515"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1518">}</pre>
</pre>
文件上传优化分析
-
文件名称写死的问题
服务端,保存文件的名称如果写死,那么最终导致服务器硬盘,只会保留一个文件,建议使用系统时间优化,保证文件名称唯一,代码如下:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="1527" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="258" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1545">FileOutputStream fis = new FileOutputStream(System.currentTimeMillis()+".jpg") // 文件名称</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1557">BufferedOutputStream bos = new BufferedOutputStream(fis);</pre>
</pre>
-
循环接收的问题
服务端,指保存一个文件就关闭了,之后的用户无法再上传,这是不符合实际的,使用循环改进,可以不断的接收不同用户的文件,代码如下:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="1569" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="259" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1587">// 每次接收新的连接,创建一个Socket</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1590">while(true){</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1593"> Socket accept = serverSocket.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1600"> ......</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1602">}</pre>
</pre>
-
效率问题
服务端,在接收大文件时,可能耗费几秒钟的时间,此时不能接收其他用户上传,所以,使用多线程技术优化,代码如下:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="1608" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="260" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1626">while(true){</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1629"> Socket accept = serverSocket.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1636"> // accept 交给子线程处理.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1639"> new Thread(() -> {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1644"> ......</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1647"> InputStream bis = accept.getInputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1654"> ......</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1657"> }).start();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1660">}</pre>
</pre>
优化实现
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="1666" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="261" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1684">public class FileUpload_Server {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1689"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1699"> System.out.println("服务器 启动..... ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1705"> // 1. 创建服务端ServerSocket</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1708"> ServerSocket serverSocket = new ServerSocket(6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1716"> // 2. 循环接收,建立连接</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1720"> while (true) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1724"> Socket accept = serverSocket.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1731"> /* </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1735"> 3. socket对象交给子线程处理,进行读写操作</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1739"> Runnable接口中,只有一个run方法,使用lambda表达式简化格式</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1742"> */</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1745"> new Thread(() -> {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1750"> try (</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1753"> //3.1 获取输入流对象</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1756"> BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1765"> //3.2 创建输出流对象, 保存到本地 .</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1768"> FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1779"> BufferedOutputStream bos = new BufferedOutputStream(fis);) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1787"> // 3.3 读写数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1790"> byte[] b = new byte[1024 * 8];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1800"> int len;</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1804"> while ((len = bis.read(b)) != -1) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1815"> bos.write(b, 0, len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1822"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1824"> //4. 关闭 资源</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1827"> bos.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1831"> bis.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1835"> accept.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1839"> System.out.println("文件上传已保存");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1845"> } catch (IOException e) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1850"> e.printStackTrace();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1855"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1857"> }).start();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1860"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1862"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1864">}</pre>
</pre>
信息回写分析图解
前四步与基本文件上传一致.
- 【服务端】获取输出流,回写数据。
- 【客户端】获取输入流,解析回写数据。
[图片上传失败...(image-5fcd74-1580309731409)]
回写实现
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="1876" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="262" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1894">public class FileUpload_Server {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1899"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1909"> System.out.println("服务器 启动..... ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1915"> // 1. 创建服务端ServerSocket</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1918"> ServerSocket serverSocket = new ServerSocket(6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1926"> // 2. 循环接收,建立连接</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1929"> while (true) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1933"> Socket accept = serverSocket.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1940"> /*</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1944"> 3. socket对象交给子线程处理,进行读写操作</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1948"> Runnable接口中,只有一个run方法,使用lambda表达式简化格式</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1951"> */</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1954"> new Thread(() -> {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1959"> try (</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1962"> //3.1 获取输入流对象</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1965"> BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1974"> //3.2 创建输出流对象, 保存到本地 .</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1977"> FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1988"> BufferedOutputStream bos = new BufferedOutputStream(fis);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1996"> ) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="1998"> // 3.3 读写数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2001"> byte[] b = new byte[1024 * 8];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2011"> int len;</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2015"> while ((len = bis.read(b)) != -1) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2026"> bos.write(b, 0, len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2033"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2035"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2038"> // 4.=======信息回写===========================</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2041"> System.out.println("back ........");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2047"> OutputStream out = accept.getOutputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2054"> out.write("上传成功".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2060"> out.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2064"> //================================</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2067"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2070"> //5. 关闭 资源</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2073"> bos.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2077"> bis.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2081"> accept.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2085"> System.out.println("文件上传已保存");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2091"> } catch (IOException e) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2096"> e.printStackTrace();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2100"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2102"> }).start();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2105"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2107"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2109">}</pre>
</pre>
客户端实现:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="2114" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="263" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2132">public class FileUpload_Client {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2137"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2147"> // 1.创建流对象</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2150"> // 1.1 创建输入流,读取本地文件</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2153"> BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg"));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2163"> // 1.2 创建输出流,写到服务端</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2166"> Socket socket = new Socket("localhost", 6666);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2175"> BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2184"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2187"> //2.写出数据.</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2190"> byte[] b = new byte[1024 * 8 ];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2200"> int len ;</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2204"> while (( len = bis.read(b))!=-1) {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2214"> bos.write(b, 0, len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2221"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2223"> // 关闭输出流,通知服务端,写出数据完毕</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2227"> socket.shutdownOutput();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2231"> System.out.println("文件发送完毕");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2237"> // 3. =====解析回写============</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2240"> InputStream in = socket.getInputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2247"> byte[] back = new byte[20];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2255"> in.read(back);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2260"> System.out.println(new String(back));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2268"> in.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2272"> // ============================</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2275"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2278"> // 4.释放资源</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2281"> socket.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2285"> bis.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2289"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2291">}</pre>
</pre>
3.2 模拟B\S服务器(扩展知识点)
模拟网站服务器,使用浏览器访问自己编写的服务端程序,查看网页效果。
案例分析
-
准备页面数据,web文件夹。
复制到我们Module中,比如复制到day08中
[图片上传失败...(image-18826d-1580309731401)]
-
我们模拟服务器端,ServerSocket类监听端口,使用浏览器访问
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="2304" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="264" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2322">public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2332"> ServerSocket server = new ServerSocket(8000);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2341"> Socket socket = server.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2349"> InputStream in = socket.getInputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2357"> byte[] bytes = new byte[1024];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2366"> int len = in.read(bytes);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2375"> System.out.println(new String(bytes,0,len));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2386"> socket.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2391"> server.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2396">}</pre>
</pre>
[图片上传失败...(image-5fca54-1580309731401)]
-
服务器程序中字节输入流可以读取到浏览器发来的请求信息
[图片上传失败...(image-511543-1580309731401)]
GET/web/index.html HTTP/1.1是浏览器的请求消息。/web/index.html为浏览器想要请求的服务器端的资源,使用字符串切割方式获取到请求的资源。
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" data-evernote-id="2401" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="265" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2419">//转换流,读取浏览器请求第一行</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2422">BufferedReader readWb = new BufferedReader(new InputStreamReader(socket.getInputStream()));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2433">String requst = readWb.readLine();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2440">//取出请求资源的路径</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2443">String[] strArr = requst.split(" ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2451">//去掉web前面的/</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2454">String path = strArr[1].substring(1);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2463">System.out.println(path);</pre>
</pre>
案例实现
服务端实现:
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="2474" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="266" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2492">public class SerDemo {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2497"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2507"> System.out.println("服务端 启动 , 等待连接 .... ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2513"> // 创建ServerSocket 对象</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2516"> ServerSocket server = new ServerSocket(8888);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2524"> Socket socket = server.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2531"> // 转换流读取浏览器的请求消息</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2534"> BufferedReader readWb = new</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2540"> BufferedReader(new InputStreamReader(socket.getInputStream()));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2547"> String requst = readWb.readLine();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2554"> // 取出请求资源的路径</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2557"> String[] strArr = requst.split(" ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2565"> // 去掉web前面的/</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2568"> String path = strArr[1].substring(1);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2577"> // 读取客户端请求的资源文件</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2580"> FileInputStream fis = new FileInputStream(path);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2588"> byte[] bytes= new byte[1024];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2596"> int len = 0 ;</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2602"> // 字节输出流,将文件写会客户端</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2605"> OutputStream out = socket.getOutputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2612"> // 写入HTTP协议响应头,固定写法</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2615"> out.write("HTTP/1.1 200 OK\r\n".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2621"> out.write("Content-Type:text/html\r\n".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2627"> // 必须要写入空行,否则浏览器不解析</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2630"> out.write("\r\n".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2636"> while((len = fis.read(bytes))!=-1){</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2646"> out.write(bytes,0,len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2653"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2655"> fis.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2659"> out.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2663"> readWb.close(); </pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2668"> socket.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2672"> server.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2676"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2678">}</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2680"></pre>
</pre>
访问效果
- 火狐
[图片上传失败...(image-972718-1580309731408)]
小贴士:不同的浏览器,内核不一样,解析效果有可能不一样。
发现浏览器中出现很多的叉子,说明浏览器没有读取到图片信息导致。
浏览器工作原理是遇到图片会开启一个线程进行单独的访问,因此在服务器端加入线程技术。
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded js-evernote-checked" style="page-break-inside: unset;" data-evernote-id="2693" lang="java">
<textarea autocorrect="off" autocapitalize="off" spellcheck="false" tabindex="0" style="position: absolute; bottom: -1em; padding: 0px; width: 1000px; height: 1em; outline: none;" data-evernote-id="267" class="js-evernote-checked"></textarea>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2711">public class ServerDemo {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2716"> public static void main(String[] args) throws IOException {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2726"> ServerSocket server = new ServerSocket(8888);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2734"> while(true){</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2738"> Socket socket = server.accept();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2745"> new Thread(new Web(socket)).start();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2753"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2755"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2757"> static class Web implements Runnable{</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2764"> private Socket socket;</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2769"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2772"> public Web(Socket socket){</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2778"> this.socket=socket;</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2784"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2786"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2789"> public void run() {</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2794"> try{</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2797"> //转换流,读取浏览器请求第一行</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2800"> BufferedReader readWb = new</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2806"> BufferedReader(new InputStreamReader(socket.getInputStream()));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2813"> String requst = readWb.readLine();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2820"> //取出请求资源的路径</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2823"> String[] strArr = requst.split(" ");</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2831"> System.out.println(Arrays.toString(strArr));</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2839"> String path = strArr[1].substring(1);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2848"> System.out.println(path);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2854"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2857"> FileInputStream fis = new FileInputStream(path);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2865"> System.out.println(fis);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2871"> byte[] bytes= new byte[1024];</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2879"> int len = 0 ;</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2885"> //向浏览器 回写数据</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2888"> OutputStream out = socket.getOutputStream();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2895"> out.write("HTTP/1.1 200 OK\r\n".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2901"> out.write("Content-Type:text/html\r\n".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2908"> out.write("\r\n".getBytes());</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2914"> while((len = fis.read(bytes))!=-1){</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2924"> out.write(bytes,0,len);</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2931"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2933"> fis.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2937"> out.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2941"> readWb.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2945"> socket.close();</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2949"> }catch(Exception ex){</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2954"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2957"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2959"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2961"> }</pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2963"></pre>
<pre class="CodeMirror-line js-evernote-checked" role="presentation" data-evernote-id="2967">}</pre>
</pre>
访问效果:
[图片上传失败...(image-a9f08e-1580309731408)]
图解:
[图片上传失败...(image-3b4c9f-1580309731408)]