Java Day17

Java

day17_2023.8.31

序列化,反序列化

1,序列化:指的是,将Java对象转换为字节序列的过程,可以持久化存储到磁盘或者在网络上传输

2,反序列化:指的是,将字节序列再恢复成Java对象的过程

​ 作用:在传递或者保存对象的时候,保证对象的完整性和可传递性

怎么实现序列化和反序列化?

​ 序列化和反序列化的对象,要实现一个serializable接口

​ Serializable接口中没有任何方法需要实现类实现,主要的作用就是用来标识可序列化的语义

​ 实现Serializable接口 的类,才可以被 ObjectInputStream和ObjectOutputStream识别,才可以被读取或者写出

public class Demo {
    public static void main(String[] args) {
        ObjectInputStream ois = null;
        ObjectOutputStream ous = null;
        try {

            //序列化对象
            ous = new ObjectOutputStream(new FileOutputStream("D:\\student.txt"));

            //创建要被序列化的对象
            Student s1 = new Student(1001, "jack", "1班");
            System.out.println(s1);

            //将对象序列化
            ous.writeObject(s1);

            //将对象反序列化
            //反序列化对象
            ois = new ObjectInputStream(new FileInputStream("D:\\student.txt"));
            //反序列化返回的是Object对象,需要强转为Student
            Object object = ois.readObject();
            Student s2 = (Student) object;

            System.out.println(s2);

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }finally {

            try {
                if (ois != null){ois.close();}
                if (ous != null){ ous.close();}
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


public class Student implements Serializable {
    private int sid;
    private String name;
    private String className;

    public Student(int sid, String name, String className) {
        this.sid = sid;
        this.name = name;
        this.className = className;
    }



    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", name='" + name + '\'' +
                ", className='" + className + '\'' +
                '}';
    }
}

通过IO流实现二进制文件的读写

/*
二进制文件的读写(文件复制)
 */
public class BinaryFileIO {
    public static void main(String[] args) {
        //DataInputStream  DataOutputStream
                FileInputStream fis = null;
                DataInputStream dis =null;
                FileOutputStream fos =null;
                DataOutputStream dos =null;
        try {
            //创建文件输入流FileInputStream
            fis = new FileInputStream("D:\\1.jpg");
            //通过文件输入流创建 数据输入流DataInputStream
            dis = new DataInputStream(fis);
            //创建文件输入流FileInputStream
            fos = new FileOutputStream("E:\\abc.jpg");
            //通过文件输入流创建 数据输入流DataInputStream
            dos = new DataOutputStream(fos);
            int data;
            //读的同时,将内容写出去
            while ((data = dis.read()) != -1){
                dos.write(data);
            }
            System.out.println("文件复制成功");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                dos.close();
                fos.close();
                dis.close();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

计算机中的编码格式

在计算机中,任何文字都是以指定的编码方式存在的

Java中常见的编码格式 : ISO8859-1,GBK,UTF编码,Unicode

编码格式说明 :

ISO8859-1 : 属于单字节编码,最多只能标识0-255的字符范围

GBK: 中文的国标编码,用来标识汉字,属于双字节编码,可以用来标识简体字和繁体字

**UTF:**兼容了 ISO8859-1编码,同时又可以用来表示所有的语言字符,UTF是不定长编码,每个字符长度为1-6个字节不等,一般在中文网页使用此编码,可以节省空间,常用的一般是UTF-8

Unicode: 是一种编码规范,为了解决全球字符通用编码而设计的。UTF-8和UTF-16都是这个规范的一种实现,不兼容ISO8859-1 ,Java内部采用次编码规范

IO流中解决乱码问题:

public class BufferedReaderDemo {
    public static void main(String[] args) {
        try {
            FileInputStream is = new FileInputStream("D:\\hello.txt");

            //指定编码格式,格式跟文件的编码格式对应
            InputStreamReader isr = new InputStreamReader(is, "GBK");
            BufferedReader bufferedReader = new BufferedReader(isr);
            String data ;
            while ( (data = bufferedReader.readLine()) != null){
                System.out.println(data);
            }
            //int data;
            //while ( (data = is.read()) != -1){
            //    System.out.println((char) data);
            //}
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

网络编程

Java编写的程序,需要在网络上运行,Java程序也需要实现在网络上的数据连通。

Java中提供了一些网络相关的类库,可以让用户实现网络连接

Java实现了一个跨平台的网络库,程序员将来可以使用这种统一的编程环境完成网络连接功能

计算机网络

计算机网络指的是,通过通信线路,将地理位置不同的计算机连接起来,在操作系统、网络管理软件、网络通信协议的管理下,完成信息传递以及资源的共享

网络通信协议:

计算机网络中实现通信功能,必须要遵循的一些约定,就是通信协议

Java中的网络编程:

直接或者间接的通过网络通信协议,和其他计算机实现数据交互,进行通信

网络编程实现通信的关键点 :

1,如何准确的定位网络上的一台或者多台主机?

通过ip地址定位主机,通过端口号定位主机上的应用

2,找到主机后,怎么进行高效可靠的数据传输?

通过规定的传输协议 ,TCP/UDP协议

Java网络编程三要素

1,ip地址 : InetAddress

2,端口号

3,TCP/UDP协议

InetAddress类

此类表示Internet协议(IP)地址。IP地址是每台计算机在网络上的唯一标识地址

本地主机的IP地址 : 127.0.0.1 ,主机名 : localhost

IP地址分类 :

分类方式1:

IPV4和IPV6

IPV4:由4个字节,一共32位二进制数值组成, 4个 0-255范围的数值

IPV6:128位,16个字节,写成8个无符号整数,每个整数用4个16进制标识,数字之间用:隔开

分类方式2:

公网地址和私有地址, 192.168 开头的就是私有地址

public class IneAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
        //1,直接通过主机名称,来获取主机IneAddress地址对象
        InetAddress address1 = InetAddress.getByName("localhost");
        System.out.println(address1);
        InetAddress address2 = InetAddress.getByName("127.0.0.1");
        System.out.println(address2);

        //2,static InetAddress getLocalHost()
        //返回本地主机的地址。 计算机名称 + ip地址
        InetAddress address3 = InetAddress.getLocalHost();
        System.out.println(address3);

        //3,获取某个网站的地址
        InetAddress address4 = InetAddress.getByName("www.baidu.com");
        System.out.println(address4);

        //其他方法的使用
        System.out.println(address1.getAddress());
        System.out.println(address1.getHostName());
        System.out.println(address1.getHostAddress());

    }
}
端口号的使用

端口用来表示计算机上运行的程序(具体的某个应用)

网络通信,本质上就是应用程序的通信,端口号,就是用来区分每个计算机上不同的应用程序的

端口号 :是一个16位的整数,0-65535的范围

TCP和UDP各有65535个端口,每个协议下的端口不能冲突

公认端口: 0-1023 被预先定义的服务器通信占用端口

常见端口 :

http: 80 https: 443 ftp: 21 telnet : 23 ssh : 22

注册端口 : 1024 - 49151 分配给用户进程或者应用程序的

常用的端口:

tomcat : 8080 mysql : 3306 oracle :1521

私有端口 : 49152 - 65535

netstat -ano 命令 用来查看端口

套接字对象Socket

ip地址和端口号组成的一个用来标识主机应用的类.

该类实现客户端套接字(也称为“套接字”)。 套接字是两台机器之间通讯的端点。

常用类

InetSocketAddress 该类实现IP套接字地址(IP地址+端口号)它也可以是一对(主机名+端口号)

public class SocketDemo {
    public static void main(String[] args) throws IOException {
        Socket socket = 
                new Socket(InetAddress.getByName("localhost"), 8080);
        InetSocketAddress inetSocketAddress = 
                new InetSocketAddress("127.0.0.1", 8181);
    }
}

通信协议

网络通信协议 :计算机网络中,遵循的一些约定,主要是对于 数据的传输速度、传输的代码、代码结构、传输控制步骤、错误信息控制等信息指定的一些标准

通信双方必须同时遵守这些约定才能完成数据交互

网络协议的实现方式 ?

通过将网络协议分层,每一个层,处理不同的事情,最终完成协议的约定

分层的内容 : 物理层、数据链路层、网络层、传输层、应用层

传输层的两个重要的协议 :

TCP(Transmission Control Protocol) : 传输控制协议

UDP(User Datagram Protocol) : 用户数据报协议

TCP协议

使用TCP协议之前,必须要建立TCP连接,形成传输数据通道

传输前,采用的 三次握手的方式,点对点建立连接,完成通信,是可靠的,安全的传输协议

在网络编程中,需要创建两个接口 : 客户端接口 、 服务端的接口

TCP可以进行大量的数据传输

传输完之后,需要释放建立的连接,效率相对较低一些

UDP协议

将数据、源、目的 封装成数据包,不需要建立连接

每个数据包大小限制在64kb以内

发送的时候,不去查看接收方是否准好,接收方收到后,也不会告诉发送方,收到数据

UDP是一种不可靠的传输

发送数据结束后,不需要释放资源,开销小,速度快

使用TCP完成数据传输

需求 :用户在客户端发送消息给服务端,服务端将数据展示在控制台上

/*
客户端
 */
public class TcpClient {
    public static void main(String[] args) {
        //使用tcp完成数据发送
        //步骤:
        OutputStream os = null;
        Socket socket = null;
        try {
            //1,找到服务器,建立连接
            //获取服务器地址对象,以及端口号
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            //指定端口号,不要和本机上的端口号冲突了
            int port = 8888;
            //2,发送数据,通过ip+port 创建 Socket对象发送数据
           socket = new Socket(serverIP, port);
            //获取输出流outputStream
            os = socket.getOutputStream();
            os.write("你好,我是南邮的学生!".getBytes());
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //3,关闭资源
            try {
                if (os != null){
                    os.close();
                }
                if (socket != null){
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
/*
服务端
 */
public class TcpServer {
    public static void main(String[] args) {
        ByteArrayOutputStream baos = null;
        InputStream is = null;
        Socket accept = null;
        ServerSocket serverSocket = null;
        //步骤:
        //1,建立服务端的端口,创建ServerSocket对象
        try {
             serverSocket = new ServerSocket(8888);
            //2,等待用户连接
            while (true){
                //侦听用户连接
                accept = serverSocket.accept();
                //3,接收用户消息
                //获取输入流,读到数据
                 is = accept.getInputStream();
                //使用ByteArrayOutputStream,将数据写出去
                 baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int data;
                while ((data = is.read(buffer)) != -1){
                    baos.write(buffer,0,data);
                }
                System.out.println(baos.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                baos.close();
                is.close();
                accept.close();
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

使用TCP完成文件的上传,服务器收到上传文件,会返回一条信息给客户端,提示文件接收成功

/*
客户端
 */
public class TcpClient {
    public static void main(String[] args) {
        //使用tcp完成数据发送
        //步骤:
        OutputStream os = null;
        Socket socket = null;
        try {
            //1,找到服务器,建立连接
            //获取服务器地址对象,以及端口号
            InetAddress serverIP =
                    InetAddress.getByName("127.0.0.1");
            //指定端口号,不要和本机上的端口号冲突了
            int port = 8888;
            //2,发送数据,通过ip+port 创建 Socket对象发送数据
           socket = new Socket(serverIP, port);
            //获取输出流outputStream
            os = socket.getOutputStream();
            //获取上传的图文件对象
            FileInputStream fis = new FileInputStream("D:\\1.jpg");
            byte[] buffer = new byte[1024];
            int data;
            //完成图片的读取和写出
            while ((data = fis.read(buffer)) != -1){
                os.write(buffer,0,data);
            }
            //传输完之后,要关闭数据输出
            socket.shutdownOutput();

            //读取服务器返回的消息
            InputStream is = socket.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[1024];
            int data1;
            while ((data1 = is.read(bytes)) != -1){
                baos.write(bytes,0,data1);
            }
            System.out.println(baos.toString());

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //3,关闭资源
            try {
                if (os != null){
                    os.close();
                }
                if (socket != null){
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

/*
服务端
 */
public class TcpServer {
    public static void main(String[] args) {
        InputStream is = null;
        Socket accept = null;
        ServerSocket serverSocket = null;
        OutputStream os = null;
        FileOutputStream fos = null;
        //步骤:
        //1,建立服务端的端口,创建ServerSocket对象
        try {
             serverSocket = new ServerSocket(8888);
            //2,等待用户连接
            //while (true){
                //侦听用户连接
                accept = serverSocket.accept();
                //3,接收用户消息
                //获取输入流,读到数据
                 is = accept.getInputStream();
                //创建文件输出对象
                fos = new FileOutputStream(new File("abc.jpg"));
                byte[] buffer = new byte[1024];
                int data;
                while ((data = is.read(buffer)) != -1){
                    fos.write(buffer,0,data);
                }
                //通知客户端
                 os = accept.getOutputStream();
                os.write("文件接收成功".getBytes());
            //}
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                os.close();
                fos.close();
                is.close();
                accept.close();
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

UDP实现数据传输

UDP传输需要封装一个数据包,Java中的数据包其实就是一个对象

DatagramPacket:该类表示数据报包。 数据包中,包含发送的 ip、端口、接收端的ip、端口、数据

DatagramSocket:此类表示用于发送和接收数据报数据包的套接字,UDP通过此类发送和接收数据

/*
UDP的客户端
 */
public class UdpClient {
    public static void main(String[] args) throws IOException {
        //1,创建DatagramSocket对象
        DatagramSocket socket = new DatagramSocket();
        byte[] data = "你好,udp发送数据".getBytes();
        InetAddress address = InetAddress.getByName("127.0.0.1");
        //2,封装数据包
        DatagramPacket packet =
                new DatagramPacket(data, 0, data.length, address, 9999);
        //3,通过socket发送数据包
        socket.send(packet);
        socket.close();
    }
}



/*
udp的接收方
 */
public class UdpServer {
    public static void main(String[] args) throws IOException {
        //建立DatagramSocket对象,并开放端口
        DatagramSocket socket = new DatagramSocket(9999);
        //接收数据
        byte[] buffer = new byte[100];
        //创建数据包,用来接收数据
        DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
        //传入数据包接收数据
        socket.receive(packet);
        //把数据从包中取出,转为String
        byte[] data = packet.getData();
        String s = new String(data, 0, data.length);
        System.out.println(s);
        socket.close();
    }
}

使用Udp实现一个模拟在线咨询的案例

用户可以输入一些信息,服务器接收到之后,根据用户输入的信息,作出自动的回应

/*
咨询方
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class ChatClient {
    public static void main(String[] args) throws IOException {
        System.out.println("已经接入咨询系统,可以发送消息了:");

        //创建DatagramSocket对象,发送端的
        DatagramSocket sendSocket = new DatagramSocket(8888);

        //创建输入对象
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        //循环输入消息,实现发送多条消息
        while (true){
            String data = reader.readLine();
            byte[] bytes = data.getBytes();
            //放到数据包中
            DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length,new InetSocketAddress("localhost",6666));
            sendSocket.send(packet);

            // 创建接收数据包的对象
            byte[] buffer = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(buffer, buffer.length);

            // 接收服务器端的回复
            sendSocket.receive(receivePacket);

            // 提取回复内容并打印
            String response = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("收到回复: " + response);

            //如果用户发送了byebye,那么就断开
            if (data.equals("byebye")){
                break;
            }
        }
    }
}



/*
接收方
 */

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ChatServer {
    public static void main(String[] args) throws IOException {
        DatagramSocket socket = new DatagramSocket(6666);

        while (true){

            //接收数据
            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
            socket.receive(packet);

            //获取数据内容
            byte[] data = packet.getData();
            String s = new String(data,0,packet.getLength());
            System.out.println("收到消息:" + s);

            if (s.equals("你好")){
                //数据返回
                String response = "有什么需要帮助你的?";
                byte[] responseData = response.getBytes();
                DatagramPacket responsePacket = new DatagramPacket(responseData,responseData.length,packet.getSocketAddress());
                socket.send(responsePacket);
                System.out.println("发送回复:" + response);
            }else if (s.equals("byebye")){
                break;
            } else{
                String response = "对不起,我不明白您的意思";
                byte[] responseData = response.getBytes();
                DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length, packet.getSocketAddress());
                socket.send(responsePacket);
                System.out.println("发送回复:" + response);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值