Bootstrap

# 网络编程

网络编程:在通信协议下,不同计算机上运行的程序,进行的数据传输

初识网络编程

常见的网络架构

image-20240422204556071

BS架构的优缺点

  • 不需要开发客户端,只需要页面+服务器

  • 用户不需要下载,打开浏览器就可以使用

  • 如果应用过大,用户体验收到影响

CS架构的优缺点

  • 画质精美,内容丰富

  • 需要开发客户端还有服务端

  • 更新,下载,维护不方便

计算机网络

概念:将不同地区的计算机设备连接起来,通过通信线连接起来在网络操作,网络管理软件,及网络通信协议的管理下实现资源共享和信息传递的计算机系统

目的:传播交流信息,数据交换,通信

想要达到这个效果需要什么:

1.端口,定位到这个计算机上的某个资源

2.传输数据:

javaWeb:网页编程 架构:B/S

网络编程:TCP/IP 架构:C/S

网络通信要素

网络通信三要素:

  • IP:设备在网络中的标识

  • 端口号:应用软件在电脑上的标识

  • 通信协议:数据传输规则

人工智能:智能汽车:只能用在工厂,已经非常成熟了,但存在伦理问题

通过ip和端口号就可以定位到一个具体的计算机

规则:网络通信协议

HTTP

TCP/IP参考模型

image-20240128111201681

1.网络编程中有两个主要问题

  • 如何准确的定位到网络上的一台或多台主机

  • 找到主机后如何进行通信

win+r

ping www.baidu.com

2.网络编程中的要素

  • IP和端口号

  • 网络通信协议

3.万物皆对象

IP

概念:互联网协议

IP地址:InetAddress

  1. 唯一定位一台计算机网络

2.本机localhost:127.0.0.1

3.IP地址的分类:

  • ipv4:

127.0.0.1,四个字节组成,30亿都在北美,四亿在亚洲,已经用完

互联网通信协议第四版,前三版都是不对外的,因此市面上的协议就是直接从四开始的

  • IPV6:

新造的IP,采取128位地址长度,分成八组

互联网通信协议的第六版,第五版应该也是被淘汰了

image-20240425163004891

  • 公网(互联网)-私网(局域网)

    image-20240128112929203

abcd类协议:一段一段折

192.168.xx.xx,专门给组织内部使用的

假设给你分配了一个这种的局域网,那么,你在不同的位置上网,IP不一定相同,但是本机的IP一定是固定的

常见的CMD命令:

  • inconfig:查看本机IP地址

image-20240425164110799

  • ping:检查网络是否连通

image-20240425164044619

域名:记忆IP问题

Ip:www.vip.com

域名的本质其实也是IP

com是全球的,cn是中国的

 package comm.itheima.SoftwareProgramming;
 ​
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 ​
 public class test1 {
     public static void main(String[] args){
         //1.获取inetAddress对象
         InetAddress address = null;
         try {
             address = InetAddress.getByName("LAPTOP-S2VETHFD");
         } catch (UnknownHostException e) {
             throw new RuntimeException(e);
         }
         //2.从InetAddress中获取电脑的名字
         String hostName = address.getHostName();
         //3.获取电脑的IP
         String hostAddress = address.getHostAddress();
     }
 }
 public class test1 {
     //psvm主函数快捷输入
     public static void main(String[] args) {
         try {
             //获取本机IP地址
             InetAddress address = InetAddress.getByName("127.0.0.1");
             System.out.println(address);
             InetAddress localHost = InetAddress.getLocalHost();
             System.out.println(localHost);
             //查询网站IP
             InetAddress byName1 = InetAddress.getByName("www.baidu.com");
             System.out.println(byName1);
             //ip
             System.out.println(byName1.getHostAddress());
             //域名或者自己电脑的名字
             System.out.println(byName1.getHostName());
         } catch (UnknownHostException e) {
             throw new RuntimeException(e);
         }
     }
 }

端口

端口表示计算机上的一个程序的进程,IP地址好比一个计算机的标签,端口好比一个软件的标签

不同的进程有不同的端口号,用来区分软件的

被规定0~65535

TCO/UDP:65535*2 tcp:80 udp:80单个协议下不能冲突

一个端口只能是一个程序来使用

端口分类:公有端口0~1023

  • HTTP:80

  • HTTPS:443

  • FTP:21

  • Telent:23

  • 程序注册端口:2014~49151

  • Tomcat:8080

  • Mysql:3306

  • Oracle:1521

动态端口,也叫私有端口49152~65535

 //查看端口号
 netstat ~ano
 //Linux 就是根据端口号来查进程,window上没作用
 netstat ~ano|findstr "5900" #

image-20240128165207720

通信协议

网络通信协议:速率,传输码率,代码结构,传输控制,连接和通信的规则

OSI参考模型

image-20240425170517657

最开始是这种模型,我们的代码在应用层上面运行,然后一层一层传递下去,到了物理层转换成二进制数,之后传递给其他服务器,然后再一层一层传上去

TCP/IP协议簇,实际上是一种协议

image-20240425170808397

  • TCP:用户传输协议,建立连接,面向连接的通信协议,确保两台电脑网络连接之后才会发送协议,速度快,没有大小限制,数据安全

  • UDP:用户数据报协议,发信件,无需检查两台电脑之间的网络是否畅通,一次发送64K的数据,数据不安全,容易丢失

  • IP:网络互联协议

image-20240128111201681

TCP:打电话

  • 连接,稳定

  • 三次握手,四次挥手

  • 我发出信号,你回一句,我再问你一句最少连接三次,保证稳定连接

  • 我断开连接,对方确定,我再次发出,对方收到,才断开连接

  • 客户端,服务端

  • 传输完成,释放连接,效率低

image-20240506172536654

image-20240506172735169

UDP:发短信

  • 不连接,不稳定

  • 客户端,服务端:没有明确的界限

  • 不管有没有准备好,都发给你

  • DDOS:洪水攻击,饱和攻击

UDP通信程序

先运行接收端,再运行发送端

发送

 package comm.itheima.SoftwareProgramming;
 ​
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 ​
 ​
 public class test2 {
     public static void main(String[] args) throws Exception{
         //1.创建DatagramSocket对象
         DatagramSocket socket = new DatagramSocket();
         //2.将数据打包
         String name = "aaa";
         byte[] bytes = name.getBytes();
         InetAddress name1 = InetAddress.getByName("127.0.0.1");
         int port = 10086;
         DatagramPacket packet = new DatagramPacket(bytes, bytes.length, name1, port);
         //3.发送数据
         socket.send(packet);
         //4.关闭DatagramSocket
         socket.close();
     }
 }

接收

 package comm.itheima.SoftwareProgramming;
 ​
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 ​
 ​
 ​
 public class test3 {
     public static void main(String[] args) throws Exception {
         //1.创建DatagramSocket对象
         DatagramSocket socket = new DatagramSocket(10086);
         //2.接收数据
         byte[] bytes = new byte[1024];
         //将创建好的数组进行打包
         DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
         //将传输来的数据包装到包内
         //receive有阻塞功能,程序在运行到这个地方的时候会停止运行,等待发送端发送数据,之后才会执行hou'ma
         socket.receive(packet);
         //3.解析数据
         byte[] data = packet.getData();
         InetAddress address = packet.getAddress();
         int length = packet.getLength();
         int port = packet.getPort();
 ​
         System.out.println("接收到数据" + new String(data,0,length));
         System.out.println("该数据是从头" + address + "这台电脑中的" + port + "这个端口发出的");
         //4.关闭资源
         socket.close();
     }
 }

 package comm.itheima.SoftwareProgramming1;
 ​
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.util.Scanner;
 ​
 public class test1 {
     public static void main(String[] args) throws Exception {
         //1.创建DatagramSocket对象(括号里面没有指定端口号,那么就是随机端口号,但是没有什么影响,只要指定的端口号和接收的端口号一致就可以了)
         DatagramSocket socket = new DatagramSocket();
         //2.打包数据
         Scanner scanner = new Scanner(System.in);
         while(true){
             System.out.println("请输入你要传递的数据:");
             String num = scanner.next();
             //这个里面的break表示的是输入886就停止发送,886是发不过去的
             if("886".equals(num)){
                 break;
             }
             //将发送的数据转换成字节数组
             byte[] bytes = num.getBytes();
             //获取电脑发送的名称
             InetAddress address = InetAddress.getByName("127.0.0.1");
             //目标端口号
             int port = 10086;
             DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
             //3.发送数据
             socket.send(packet);
         }
         //4.关闭资源
         socket.close();
     }
 }

 
package comm.itheima.SoftwareProgramming1;
 ​
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 ​
 ​
 public class test2 {
     public static void main(String[] args) throws Exception {
         //1.获取DatagramSocket对象
         DatagramSocket socket = new DatagramSocket(10086);
         //2.获取数据包
         byte[] bytes = new byte[1024];
         DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
         while(true){
             socket.receive(packet);
             //3.解析包数据
             byte[] data = packet.getData();
             int len = packet.getLength();
             String ip = packet.getAddress().getHostAddress();
             String name = packet.getAddress().getHostName();
             //4.打印包内容
             System.out.println("ip为:" + ip + ",主机名为:" + name + "的人发送了:" + new String(data,0,len));
         }
     }
 }

单播,组播,广播

image-20240506152912218

组播的一个地址里面就有很多个设备

发送

 
package comm.itheima.multicast;
 ​
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.net.MulticastSocket;
 ​
 public class Multicastrecivicesend {
     public static void main(String[] args) throws IOException {
         //创建MulticastSocket对象
         MulticastSocket socket = new MulticastSocket();
         //将字符串数据转换成字节数组
         String name = "111";
         byte[] bytes = name.getBytes();
         //设定端口号
         int port = 10086;
         //设定端口
         InetAddress address = InetAddress.getByName("224.0.0.1");
         //将数据打包
         DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
         //发送打包好的数据
         socket.send(packet);
         //关闭资源
         socket.close();
     }
 }

接收

 package comm.itheima.multicast;
 ​
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.net.MulticastSocket;
 ​
 public class Multicastrecivice {
     public static void main(String[] args) throws IOException {
         //创建MulticastSocket对象
         MulticastSocket socket = new MulticastSocket(10086);
         //将设备添加到该ip内
         InetAddress address = InetAddress.getByName("224.0.0.1");
         socket.joinGroup(address);
         //将数据用字节数组接收
         byte[] bytes = new byte[1024];
         DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
         //将数据接收下来
         socket.receive(packet);
         //解析包数据
         byte[] data = packet.getData();
         int len = packet.getLength();
         String ip = packet.getAddress().getHostAddress();
         String name = packet.getAddress().getHostName();
         //4.打印包内容
         System.out.println("ip为:" + ip + ",主机名为:" + name + "的人发送了:" + new String(data,0,len));
     }
 }

 package comm.itheima.multicast;
 ​
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.net.MulticastSocket;
 ​
 public class Multicastrecivice2 {
     public static void main(String[] args) throws IOException {
         //创建MulticastSocket对象
         MulticastSocket socket = new MulticastSocket(10086);
         //将设备添加到该ip内
         InetAddress address = InetAddress.getByName("224.0.0.1");
         socket.joinGroup(address);
         //将数据用字节数组接收
         byte[] bytes = new byte[1024];
         DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
         //将数据接收下来
         socket.receive(packet);
         //解析包数据
         byte[] data = packet.getData();
         int len = packet.getLength();
         String ip = packet.getAddress().getHostAddress();
         String name = packet.getAddress().getHostName();
         //4.打印包内容
         System.out.println("ip为:" + ip + ",主机名为:" + name + "的人发送了:" + new String(data,0,len));
     }
 }

 package comm.itheima.multicast;
 ​
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.InetAddress;
 import java.net.MulticastSocket;
 ​
 public class Multicastrecivice3 {
     public static void main(String[] args) throws IOException {
         //创建MulticastSocket对象
         MulticastSocket socket = new MulticastSocket(10086);
         //将设备添加到该ip内
         InetAddress address = InetAddress.getByName("224.0.0.1");
         socket.joinGroup(address);
         //将数据用字节数组接收
         byte[] bytes = new byte[1024];
         DatagramPacket packet = new DatagramPacket(bytes,bytes.length);
         //将数据接收下来
         socket.receive(packet);
         //解析包数据
         byte[] data = packet.getData();
         int len = packet.getLength();
         String ip = packet.getAddress().getHostAddress();
         String name = packet.getAddress().getHostName();
         //4.打印包内容
         System.out.println("ip为:" + ip + ",主机名为:" + name + "的人发送了:" + new String(data,0,len));
     }
 }

TCP实现聊天

image-20240506164521512

发送界面

 package comm.itheima.TCP;
 ​
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.Socket;
 ​
 public class client {
     public static void main(String[] args) throws IOException {
         //创建Socket对象
         //创建的时候就会去自动连接,要是连接不上就会报错
         Socket socket = new Socket("127.0.0.1",10086);
         //从连通通道中获取输出流
         OutputStream outputStream = socket.getOutputStream();
         //写出数据,将数据转行成字节
         outputStream.write("111".getBytes());
         //释放资源
         socket.close();
         outputStream.close();
     }
 }
 ​

注意一定要判断是否为null

接收界面

 package comm.itheima.TCP;
 ​
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.ServerSocket;
 import java.net.Socket;
 ​
 public class server {
     public static void main(String[] args) throws IOException {
         //创建ServerSocket对象
         ServerSocket socket = new ServerSocket(10086);
         //验证客户端的连接
         Socket accept = socket.accept();
         //从监听管道里面获取输入流
         //InputStream inputStream = accept.getInputStream();
         int b;
         //这里读出来的数字是the total number of bytes read into the buffer,将字节的总长度读在管道流里面,当-1的时候停止
         //字节流的方式就是一个字节一个字节的读,只能读取三分之一个汉字,所以需要转换成字符流
         //InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
         //缓冲流bufferedReader
         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
         while ((b = bufferedReader.read()) != -1){
             System.out.print((char) b);
         }
         //释放资源
         socket.close();
         bufferedReader.close();
     }
 }
 ​

文件传输

 public class test4 {
     public static void main(String[] args) throws Exception {
         //建立Socket连接
         Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9000);
         //创建一个输出流
         OutputStream outputStream = socket.getOutputStream();
         //将文件转换为流
         FileInputStream fileInputStream = new FileInputStream("D:\\javacangku\\HTML\\wenjian\\a.png");
         //写出文件
         byte[] bytes = new byte[1024];
         int len;
         while((len = fileInputStream.read(bytes)) != -1){
             outputStream.write(bytes,0,len);
         }
         socket.shutdownOutput();
         InputStream inputStream = socket.getInputStream();
         //管道流,用来转换数据类型的
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         byte[] bytes1 = new byte[2014];
         int len1;
         while ((len1 = inputStream.read(bytes1)) != -1){
             byteArrayOutputStream.write(bytes1,0,len1);
         }
         socket.close();
         outputStream.close();
         fileInputStream.close();
         byteArrayOutputStream.close();
         inputStream.close();
     }
 }

 public class test5 {
     public static void main(String[] args) throws Exception {
         //创建服务
         ServerSocket serverSocket = new ServerSocket(9000);
         //创建连接
         Socket accept = serverSocket.accept();//阻塞式连接,不输入不停下
         //创建输入流
         InputStream inputStream = accept.getInputStream();
         //文件输出
         FileOutputStream fileOutputStream = new FileOutputStream("receive.png");
         byte[] bytes = new byte[1024];
         int len;
         while((len = inputStream.read(bytes)) != -1){
             fileOutputStream.write(bytes,0,len);
 ​
         }
         //接收完毕了
         OutputStream outputStream = accept.getOutputStream();
         outputStream.write("我接收完毕了,你可以断开连接了".getBytes());
         serverSocket.close();
         accept.close();
         inputStream.close();
         fileOutputStream.close();
     }
 }

案例

多发多收

 package comm.itheima1.Test1;
 ​
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.Socket;
 import java.util.Scanner;
 ​
 public class Client {
     public static void main(String[] args) throws IOException {
         //创建Socket对象
         Socket socket = new Socket("127.0.0.1", 10086);
         //键盘录入
         Scanner scanner = new Scanner(System.in);
         //获取输出流对象
         OutputStream outputStream = socket.getOutputStream();
         //将内容转换成字节写出
         while (true) {
             String name = scanner.next();
             if(name.equals("886")){
                 break;
             }
             outputStream.write(name.getBytes());
         }
         //释放资源
         socket.close();
         outputStream.close();
     }
 }

 
package comm.itheima1.Test1;
 ​
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.ServerSocket;
 import java.net.Socket;
 ​
 ​
 public class Server {
     public static void main(String[] args) throws IOException {
         //创建ServerSocket对象
         ServerSocket serverSocket = new ServerSocket(10086);
         //验证客户端的连接
         Socket accept = serverSocket.accept();
         //获取缓冲流来读取数据
         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
         int b;
         while((b = bufferedReader.read())!= -1){
             System.out.print((char) b);
         }
         //释放资源
         serverSocket.close();
         bufferedReader.close();
     }
 }

接收并反馈

 package comm.itheima1.Test1;
 ​
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.Socket;
 ​
 public class Client {
     public static void main(String[] args) throws IOException {
         //创建Socket对象
         Socket socket = new Socket("127.0.0.1", 10086);
         //获取输出流对象
         OutputStream outputStream = socket.getOutputStream();
         //将内容转换成字节写出
         String name = "111";
         outputStream.write(name.getBytes());
         socket.shutdownOutput();
         //回响数据
         InputStream inputStream = socket.getInputStream();
         int b;
         while((b = inputStream.read()) != -1){
             System.out.print((char) b);
         }
         //释放资源
         socket.close();
         outputStream.close();
     }
 }
 ​

 package comm.itheima1.Test1;
 ​
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.net.ServerSocket;
 import java.net.Socket;
 ​
 ​
 public class Server {
     public static void main(String[] args) throws IOException {
         //创建ServerSocket对象
         ServerSocket serverSocket = new ServerSocket(10086);
         //验证客户端的连接
         Socket accept = serverSocket.accept();
         //获取缓冲流来读取数据
         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
         int b;
         while((b = bufferedReader.read())!= -1){
             System.out.print((char) b);
         }
         //回响数据
         String name = "111";
         OutputStream outputStream = accept.getOutputStream();
         outputStream.write(name.getBytes());
         //释放资源
         serverSocket.close();
         bufferedReader.close();
     }
 }

上传文件

 
package comm.itheima1.Test2;
 ​
 import java.io.*;
 import java.net.Socket;
 ​
 public class Client {
     public static void main(String[] args) throws IOException {
         //创建Socket对象
         Socket socket = new Socket("127.0.0.1", 10086);
         //创建缓冲流读取文件
         BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(""));
         //创建缓冲流输出文件
         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
         byte[] bytes = new byte[1024];
         int len ;
         while((len = bufferedInputStream.read(bytes)) != -1){
             bufferedOutputStream.write(bytes,0,len);
         }
         //关闭服务器
         socket.shutdownOutput();
         //接收服务器的回写数据
         BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
         String line = bufferedReader.readLine();
         System.out.println(line);
         //释放资源
         socket.close();
     }
 }

 
package comm.itheima1.Test2;
 ​
 import java.io.*;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.UUID;
 ​
 public class Server {
     public static void main(String[] args) throws IOException {
         //创建ServerSocket对象
         ServerSocket ss = new ServerSocket(10086);
         //等待响应
         Socket socket = ss.accept();
         //从管道流里面获取数据
         BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
         //随即生成文件名,防止文件名字重复导致原来文件被覆盖
         String name = UUID.randomUUID().toString().replace("-", "");
         //向文件输出数据
         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get("D:\\javacangku\\云顶视频练习\\SoftwareProgramming\\src\\"+name)));
         //接收并输出数据
         int len;
         byte[] bytes = new byte[1024];
         while((len = bufferedInputStream.read(bytes)) != -1){
             bufferedOutputStream.write(bytes,0,len);
         }
         //回写数据,使用管道流增强输出效率
         BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
         bufferedWriter.write("111");
         bufferedWriter.newLine();
         bufferedWriter.flush();
         //释放资源
         socket.close();
         ss.close();
     }
 }
 ​

多线程版服务器

 
package comm.itheima1.Test2;
 ​
 import java.io.*;
 import java.net.ServerSocket;
 import java.net.Socket;
 ​
 public class Server {
     public static void main(String[] args) throws IOException {
         //创建ServerSocket对象
         ServerSocket ss = new ServerSocket(10086);
         while (true) {
             //等待响应
             Socket socket = ss.accept();
             new Thread(new RunnableTest(socket)).start();
         }
 ​
     }
 }

 package comm.itheima1.Test2;
 ​
 import java.io.*;
 import java.net.Socket;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.UUID;
 ​
 public class RunnableTest implements Runnable {
     Socket socket;
     public RunnableTest(Socket socket) {
         this.socket = socket;
     }
     @Override
     public void run() {
         try {
             //从管道流里面获取数据
             BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
             //随即生成文件名,防止文件名字重复导致原来文件被覆盖
             String name = UUID.randomUUID().toString().replace("-", "");
             //向文件输出数据
             BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get("D:\\javacangku\\云顶视频练习\\SoftwareProgramming\\src\\"+name)));
             //接收并输出数据
             int len;
             byte[] bytes = new byte[1024];
             while((len = bufferedInputStream.read(bytes)) != -1){
                 bufferedOutputStream.write(bytes,0,len);
             }
             //回写数据,使用管道流增强输出效率
             BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
             bufferedWriter.write("111");
             bufferedWriter.newLine();
             bufferedWriter.flush();
 ​
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
             //释放资源
             try {
                 if(socket != null){
                     socket.close();
                 }
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         }
     }
 }

线程池版服务器

 package comm.itheima1.Test2;
 ​
 import java.io.*;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 ​
 public class Server {
     public static void main(String[] args) throws IOException {
         //创建ServerSocket对象
         ServerSocket ss = new ServerSocket(10086);
         //创建线程池
         ThreadPoolExecutor executor = new ThreadPoolExecutor(
                 3,
                 16,
                 60,
                 TimeUnit.SECONDS,
                 new ArrayBlockingQueue<>(2),
                 Executors.defaultThreadFactory(),
                 new ThreadPoolExecutor.AbortPolicy()
         );
 ​
         while (true) {
             //等待响应
             Socket socket = ss.accept();
             executor.submit(new RunnableTest(socket));
         }
 ​
     }
 }

 package comm.itheima1.Test2;
 ​
 import java.io.*;
 import java.net.Socket;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.UUID;
 ​
 public class RunnableTest implements Runnable {
     Socket socket;
     public RunnableTest(Socket socket) {
         this.socket = socket;
     }
     @Override
     public void run() {
         try {
 ​
             //从管道流里面获取数据
             BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
             //随即生成文件名,防止文件名字重复导致原来文件被覆盖
             String name = UUID.randomUUID().toString().replace("-", "");
             //向文件输出数据
             BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(Files.newOutputStream(Paths.get("D:\\javacangku\\云顶视频练习\\SoftwareProgramming\\src\\"+name)));
             //接收并输出数据
             int len;
             byte[] bytes = new byte[1024];
             while((len = bufferedInputStream.read(bytes)) != -1){
                 bufferedOutputStream.write(bytes,0,len);
             }
             //回写数据,使用管道流增强输出效率
             BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
             bufferedWriter.write("111");
             bufferedWriter.newLine();
             bufferedWriter.flush();
 ​
         } catch (IOException e) {
             throw new RuntimeException(e);
         } finally {
             //释放资源
             try {
                 if(socket != null){
                     socket.close();
                 }
             } catch (IOException e) {
                 throw new RuntimeException(e);
             }
         }
     }
 }

;