Java中使用对象流进行网络信息传输的注意点

注意点一:待传输类以及类中所有属性要实现序列化接口,并且添加序列化版本号。

public class Person implements Serializable {
    //添加一个静态常量:序列化版本号
    private static final long serialVersionUID = -6844864770754661210L;
    //这里Person类只有一个整型属性,其包装类Integer的父类Number已经实现了序列化接口
    private int age;

    public Person(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

注意点二:在客户端和服务器端使用对象流传输对象则两端中待传输的类要一致

举一个例子:比如客户端用Android studio编写,服务器用IntelliJ IDEA编写。那么二者传输的类的包的声明、Import内容、以及类的内容要一样(除了代码注释以及变量的值可以不同)。当然,你在一个编译器上只用写一个类就行了。

注意点三:如果想在服务器端向客户端(反过来也是)不断传输不同内容的对象则每次都要新建一个这个对象写到流中,不然客户端接收到的一直是第一次传过来的值。

举例:待传输类为上边的Person类
服务器为:写了一个死循环不断向客户端写出对象p,p的属性年龄每次增加1。

@Test
    public void server() {

        int i = 1;
        Person p = new Person(10);//待传输的对象
        ServerSocket serverSocket = null;
        Socket accept = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            serverSocket = new ServerSocket(1080);//指名服务器端口号
            accept = serverSocket.accept();
            objectOutputStream = new ObjectOutputStream(accept.getOutputStream());//对象输出流

            while (true) {
                p.setAge(i++);//改变对象中的值
                System.out.println(p.getAge());//打印一下改变后的值
                objectOutputStream.writeObject(p);
                objectOutputStream.flush();
                Thread.sleep(1000);//阻塞1秒
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (accept != null) {
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

客户端为:

@Test
    public void client() {

        Socket socket = null;
        ObjectInputStream oin = null;
        try {
            socket = new Socket("127.0.0.1", 1080);//连接的服务器为本机
            oin = new ObjectInputStream(socket.getInputStream());

            while (true) {
                
                Object o = oin.readObject();//接收从服务器端读取来的对象
                Person p = (Person) o;//强转为person类
                System.out.println(p.getAge());//打印对象p中的年龄
                
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {

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

按理说服务器和客户端打印结果都从1开始递增的数才对
实际结果为:

在这里插入图片描述
在这里插入图片描述
服务器正常但是客户端读取到的一直是第一次传过来的值
即服务器端每次都在一个对象上改然后将其传输到客户端,那么客户端从第二次开始都认为传过来的对象与第一次的对象相同。

正确做法是每次新建一个对象写出或者深拷贝一个对象出来去写出。

将上面服务器端改一下:

@Test
    public void server() {

        int i = 1;
        ServerSocket serverSocket = null;
        Socket accept = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            serverSocket = new ServerSocket(1080);//指名服务器端口号
            accept = serverSocket.accept();
            objectOutputStream = new ObjectOutputStream(accept.getOutputStream());//对象输出流

            while (true) {

                Person person = new Person(i++);
                objectOutputStream.writeObject(person);//每次新建一个改变后的对象写出
                objectOutputStream.flush();
                System.out.println(person.getAge());//打印改变后的person
                Thread.sleep(1000);//阻塞1秒
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (accept != null) {
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

改完后结果为:
客户端正常读取了
在这里插入图片描述





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jason_圣诞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值