6. 应用案例 4 文件上传
- 编写一个服务端,和一个客户端
- 服务器端在8888端口监听
- 客户端连接到服务端,发送一张图片 e:\bg.jpg
- 服务器端接收到客户端发送的图片,保存到src下,发送"收到图片”再退出
- 客户端接收到服务端发送的“收到图片”,再退出
- 该程序要求使用StreamUtils.java,我们直接使用
import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * 此类用于演示关于流的读写方法 * */ public class StreamUtils { /** * 功能:将输入流转换成byte[], 即可以把文件的内容读入到byte[] * @param is * @return * @throws Exception */ public static byte[] streamToByteArray(InputStream is) throws Exception{ ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象 byte[] b = new byte[1024];//字节数组 int len; while((len=is.read(b))!=-1){//循环读取 bos.write(b, 0, len);//把读取到的数据,写入bos } byte[] array = bos.toByteArray();//然后将bos 转成字节数组 bos.close(); return array; } /** * 功能:将InputStream转换成String * @param is * @return * @throws Exception */ public static String streamToString(InputStream is) throws Exception{ BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder builder= new StringBuilder(); String line; while((line=reader.readLine())!=null){ builder.append(line+"\r\n"); } return builder.toString(); } }
TCPFileUploadServer.java
TCPFileUploadClient.java
6.1 创建服务器
package java学习.网络编程.TCP; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class TCPFileUploadServer { public static void main(String[] args) throws IOException { // 服务器在8888端口监听 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("服务器在8888端口监听"); // 等待连接 Socket socket = serverSocket.accept(); System.out.println( "服务端 socket=" + socket.getClass() ); } }
6.2 客户端读取文件上传文件
package java学习.网络编程.TCP; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; public class TCPFileUploadClient { public static void main(String[] args) throws Exception { // 连接服务端的8888端口 Socket socket = new Socket(InetAddress.getLocalHost(), 8888); // 文件的路径 String filePath = "e:\\bg.jpg"; // 输入流,读取图片 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); // 调用StreamUtils.streamToByteArray读取图片,获取二进制数组 byte[] bytes = StreamUtils.streamToByteArray(bis); // 通过 socket 获取到输出流, 将 bytes 数据发送给服务端 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道 socket.shutdownOutput();//设置写入数据的结束标记 // 关闭流 bos.close(); bis.close(); socket.close(); } }
6.3 服务端读取流中的文件存放在src下
package java学习.网络编程.TCP; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class TCPFileUploadServer { public static void main(String[] args) throws Exception { // 服务器在8888端口监听 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("服务器在8888端口监听"); // 等待连接 Socket socket = serverSocket.accept(); System.out.println( "服务端 socket=" + socket.getClass() ); // 输入流,读取流中数据 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); // 调用StreamUtils.streamToByteArray将输入流中的数据读到数组中 byte[] bytes = StreamUtils.streamToByteArray(bis); // 将得到 bytes 数组,写入到指定的路径,就得到一个文件了 // 路径 String filePath = "src\\bg.jpg"; // 输出流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); bos.write(bytes); // 关闭 bos.close(); bis.close(); socket.close(); serverSocket.close(); } }
6.4 服务端回复信息
package java学习.网络编程.TCP; import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class TCPFileUploadServer { public static void main(String[] args) throws Exception { // 服务器在8888端口监听 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("服务器在8888端口监听"); // 等待连接 Socket socket = serverSocket.accept(); System.out.println( "服务端 socket=" + socket.getClass() ); // 输入流,读取流中数据 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); // 调用StreamUtils.streamToByteArray将输入流中的数据读到数组中 byte[] bytes = StreamUtils.streamToByteArray(bis); // 将得到 bytes 数组,写入到指定的路径,就得到一个文件了 // 路径 String filePath = "src\\bg.jpg"; // 输出流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); bos.write(bytes); // 回复信息 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); bw.write("收到图片"); bw.flush();//把内容刷新到数据通道 // 客户端以字节流读取信息,可以设置如下结束标记 socket.shutdownOutput();//设置写入结束标记 // 关闭 bw.close(); bos.close(); bis.close(); socket.close(); serverSocket.close(); } }
6.5 服务端接收回复信息
package java学习.网络编程.TCP; import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.net.UnknownHostException; public class TCPFileUploadClient { public static void main(String[] args) throws Exception { // 连接服务端的8888端口 Socket socket = new Socket(InetAddress.getLocalHost(), 8888); // 文件的路径 String filePath = "e:\\bg.jpg"; // 输入流,读取图片 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); // 调用StreamUtils.streamToByteArray读取图片,获取二进制数组 byte[] bytes = StreamUtils.streamToByteArray(bis); // 通过 socket 获取到输出流, 将 bytes 数据发送给服务端 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); bos.write(bytes);//将文件对应的字节数组的内容,写入到数据通道 socket.shutdownOutput();//设置写入数据的结束标记 // 接收服务端回复的信息 InputStream inputStream = socket.getInputStream(); // 使用 StreamUtils 的方法,直接将 inputStream 读取到的内容 转成字符串 String s = StreamUtils.streamToString(inputStream); System.out.println(s); // 关闭流 inputStream.close(); bos.close(); bis.close(); socket.close(); } }
效果
7. netstat 指令
- netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat -an | more可以分页显示 空格下一页
- 要求在dos控制台下执行 win+r
说明:
(1) Listening表示某个端口在监听
(2)如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息.
(3)可以输入ctrl +c退出指令
netstat -a
netstat -an | more
netstat -an
可以查看哪些应用在监听端口(要用管理员的身份打开命令窗口)
8. TCP 网络通讯不为人知的秘密
当客户端连接到服务端后,实际上客户端也是通过一个端口和服务端进行通讯的,这个端口是TCP/IP来分配的,是不确定的,是随机的.