网络编程:在通信协议下,不同计算机上运行的程序,进行的数据传输
初识网络编程
常见的网络架构
BS架构的优缺点
-
不需要开发客户端,只需要页面+服务器
-
用户不需要下载,打开浏览器就可以使用
-
如果应用过大,用户体验收到影响
CS架构的优缺点
-
画质精美,内容丰富
-
需要开发客户端还有服务端
-
更新,下载,维护不方便
计算机网络
概念:将不同地区的计算机设备连接起来,通过通信线连接起来,在网络操作,网络管理软件,及网络通信协议的管理下实现资源共享和信息传递的计算机系统
目的:传播交流信息,数据交换,通信
想要达到这个效果需要什么:
1.端口,定位到这个计算机上的某个资源
2.传输数据:
javaWeb:网页编程 架构:B/S
网络编程:TCP/IP 架构:C/S
网络通信要素
网络通信三要素:
-
IP:设备在网络中的标识
-
端口号:应用软件在电脑上的标识
-
通信协议:数据传输规则
人工智能:智能汽车:只能用在工厂,已经非常成熟了,但存在伦理问题
通过ip和端口号就可以定位到一个具体的计算机
规则:网络通信协议
HTTP
TCP/IP参考模型
1.网络编程中有两个主要问题
-
如何准确的定位到网络上的一台或多台主机
-
找到主机后如何进行通信
win+r
ping www.baidu.com
2.网络编程中的要素
-
IP和端口号
-
网络通信协议
3.万物皆对象
IP
概念:互联网协议
IP地址:InetAddress
-
唯一定位一台计算机网络
2.本机localhost:127.0.0.1
3.IP地址的分类:
-
ipv4:
127.0.0.1,四个字节组成,30亿都在北美,四亿在亚洲,已经用完
互联网通信协议第四版,前三版都是不对外的,因此市面上的协议就是直接从四开始的
-
IPV6:
新造的IP,采取128位地址长度,分成八组
互联网通信协议的第六版,第五版应该也是被淘汰了
-
公网(互联网)-私网(局域网)
abcd类协议:一段一段折
192.168.xx.xx,专门给组织内部使用的
假设给你分配了一个这种的局域网,那么,你在不同的位置上网,IP不一定相同,但是本机的IP一定是固定的
常见的CMD命令:
-
inconfig:查看本机IP地址
-
ping:检查网络是否连通
域名:记忆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" #
通信协议
网络通信协议:速率,传输码率,代码结构,传输控制,连接和通信的规则
OSI参考模型
最开始是这种模型,我们的代码在应用层上面运行,然后一层一层传递下去,到了物理层转换成二进制数,之后传递给其他服务器,然后再一层一层传上去
TCP/IP协议簇,实际上是一种协议
-
TCP:用户传输协议,建立连接,面向连接的通信协议,确保两台电脑网络连接之后才会发送协议,速度快,没有大小限制,数据安全
-
UDP:用户数据报协议,发信件,无需检查两台电脑之间的网络是否畅通,一次发送64K的数据,数据不安全,容易丢失
-
IP:网络互联协议
TCP:打电话
-
连接,稳定
-
三次握手,四次挥手
-
我发出信号,你回一句,我再问你一句最少连接三次,保证稳定连接
-
我断开连接,对方确定,我再次发出,对方收到,才断开连接
-
客户端,服务端
-
传输完成,释放连接,效率低
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));
}
}
}
单播,组播,广播
组播的一个地址里面就有很多个设备
发送
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实现聊天
发送界面
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);
}
}
}
}