JAVA使用ByteArrayOutputStream、ByteArrayInputStream将对象序列化反序列化,通过JAVA socket实现对象在网络中传输

1.序列化和反序列化:
  • 序列化是对象(类的实例)转换成字节数组或者字符串通过网络传输或者存储到本地文件。反序列化:就是将字节数组或字符串在转换成对象实例的过程。
  • (因为在网络中传输或者写本地文件,是不能使用对象的,tcp握手之后会建立一个字节流管道传输数据,所以要将对象转换序列化成字节序列)
2.ByteArrayOutputStream、ByteArrayInputStream:
  • 这两个流实际就内存流:顾名思义就是将数据写入内存,从内存中读取数据;
  • ByteArrayOutputStream:字节数组输出流在内存中创建一个字节数组缓冲区,所有发送到输出流的数 据保存在该字节数组缓冲区中。实际作用就是通过write()将对象各个字段写入一个字节数组,然后在使用toByteArray()将字节数据取出来,通过tcp传输给服务器
  • ByteArrayInputStream:字节数组输入流在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区中。实际就是将客户端发送过来的消息转成byte数组,存入内存,在分批次读取数据。

代码如下:

  • 实例类:
    我这里实体类数据类型是这样的:类型和子类型都是1字节,长度是4字节就是一个int,实际数据包含两部分UUID+数据

在这里插入图片描述
(代码免费下载链接在最后)

public class Message implements Serializable {

    public int type;                //类型    1字节
    public int subtype;             //子类型   1字节
    public int dataLength;          //数据内容长度    4字节
    public String uniqueIdentifies;    //唯一标识  16字节
    public String details = "";             //具体内容  N字节

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public int getSubtype() {
        return subtype;
    }

    public void setSubtype(int subtype) {
        this.subtype = subtype;
    }

    public int getDataLength() {
        return dataLength;
    }

    public void setDataLength(int dataLength) {
        this.dataLength = dataLength;
    }

    public String getUniqueIdentifies() {
        return uniqueIdentifies;
    }
    
    public void setUniqueIdentifies(String uniqueIdentifies) {
        this.uniqueIdentifies = uniqueIdentifies;
    }

    public String getDetails() {
        return details;
    }

    public void setDetails(String details) {
        this.details = details;
    }

    @Override
    public String toString() {
        return "Message{" +
                "type=" + type +
                ", subtype=" + subtype +
                ", dataLength=" + dataLength +
                ", uniqueIdentifies='" + uniqueIdentifies + '\'' +
                ", details='" + details + '\'' +
                '}';
    }
}

  • 客户端:
public class TcpClient {
    private String host = "localhost";
    private int port = 8189;

    public TcpClient() {
    }

    public TcpClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void chat(){
        try {
            Socket socket = new Socket(host,port);
            ByteArrayOutputStream bArray = new ByteArrayOutputStream();

            try {
                DataOutputStream out = new DataOutputStream(socket.getOutputStream());
                //序列化对象合并写入内存
                Message message = setMessage();
                System.out.println(message.details);

                bArray.write(message.getType());

                bArray.write(message.getSubtype());

                byte[] bytes1 = intToByte(message.getDataLength());

                bArray.write(bytes1,0,bytes1.length);

                bArray.write(message.uniqueIdentifies.getBytes(), 0, message.uniqueIdentifies.length());
                //这里分开写中文不会乱码了,如果message.details.getBytes()直接加入的write里会出现中文乱码
                byte[] bytes2 = message.details.getBytes();
                bArray.write(bytes2, 0, bytes2.length);
                bArray.flush();

                byte[] bytes = bArray.toByteArray();

                String result = new String(bytes);
                out.writeUTF(result);
            }finally {
                bArray.close();
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        new TcpClient().chat();

    }

    public Message setMessage(){
        Message message = new Message();
        message.setType(0x01);
        message.setSubtype(0x01);
        message.setDetails("春❥(^_-)");
        message.setDataLength(16+message.getDetails().length());
        //16字节的UUID随便编的或者自己写个方法造也行(或者API注意16个字节,如果是多个字节需要自行修改服务器参数)
        message.setUniqueIdentifies(new String("WHDISakcmqSiamSq"));
        return message;
    }
	//将int转换成四字节
    public byte[] intToByte(int res) {
        byte[] targets = new byte[4];
        targets[0] = (byte) (res & 0xff);// 最低位
        targets[1] = (byte) ((res >> 8) & 0xff);// 次低位
        targets[2] = (byte) ((res >> 16) & 0xff);// 次高位
        targets[3] = (byte) (res >>> 24);// 最高位,无符号右移。
        return targets;
    }
}
  • 服务器:
package org2.server;

import org2.message.Message;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @author Chun
 * @create 2020-07-30 15:24
 **/
public class TcpServer {
    private int port = 8189;
    
    public TcpServer() {
    }
    
    public TcpServer(int port) {
        this.port = port;
    }

    public void service() {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            Socket socket = serverSocket.accept();
            ByteArrayInputStream bInArray = null;
            try {
                DataInputStream in = new DataInputStream(socket.getInputStream());
                String s = in.readUTF();
                byte[] bytes = s.getBytes();
                int realLength = bytes.length;

                System.out.println("realLength:" + realLength);
                bInArray = new ByteArrayInputStream(bytes);

                Message message = new Message();
                message.setType(bInArray.read());
                message.setSubtype(bInArray.read());

                byte[] bytesDataLength = new byte[4];
                bInArray.read(bytesDataLength, 0, 4);
                int i = byteToInt(bytesDataLength);
                message.setDataLength(i);

                byte[] byteUniqueIdentifies = new byte[16];
                bInArray.read(byteUniqueIdentifies, 0, 16);
                message.setUniqueIdentifies(new String(byteUniqueIdentifies));

                byte[] byteDetails = new byte[realLength - 22];
                bInArray.read(byteDetails, 0, realLength - 22);
                message.setDetails(new String(byteDetails));

                System.out.println(message);

            } finally {
                socket.close();
                serverSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public int byteToInt(byte[] arr) {
        int i0 = (int) ((arr[0] & 0xff) << 0 * 8);
        int i1 = (int) ((arr[1] & 0xff) << 1 * 8);
        int i2 = (int) ((arr[2] & 0xff) << 2 * 8);
        int i3 = (int) ((arr[3] & 0xff) << 3 * 8);
        return i0 + i1 + i2 + i3;
    }
    
    public static void main(String[] args) {
        new TcpServer().service();
    }
}

TcpClient.java 下载
Message.java 下载
TcpServer.java 下载

JAVA的ObjectOutputStream不太适用把应该!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值