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;}@Overridepublic 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不太适用把应该!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437492.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】刨根究底字符编码之二——关键术语解释(下)

关键术语解释(下) 如前所述&#xff0c;现代字符编码模型共分为5层&#xff0c;下面分层进行简要介绍。 一、第1层 抽象字符表ACR (Abstract Character Repertoire抽象字符清单)&#xff1a;明确字符的范围(即确定支持哪些字符) 1. 抽象字符表ACR是一个编码系统支持的所有抽…

正则表达式来判断Sql语句中Select到from之间使用了*而不是字段名

正则&#xff1a;这里大小写转换用的java的toLowerCase()方法&#xff0c;或者自己改一改正则也可以。 \bselect\b((?!\bfrom\b).)*?\*.*?\bfrom\b主要就是用来判断select到from之间是不是用了*而不是使用字段名来进行查询&#xff0c;以此来规范Sql语句&#xff01; publ…

【转】刨根究底字符编码之三——字符编码的由来

字符编码的由来 一、为什么需要对字符进行编码 1. 计算机一开始发明出来时是用来解决数字计算问题的&#xff0c;后来人们发现&#xff0c;计算机还可以做更多的事&#xff0c;例如文本处理。 但计算机其实挺“笨”的&#xff0c;它只“认识”010110111000…这样由0和1两个数…

SpringMVC配置没问题却却找不到页面,页面显示404

在Artifacts下此工程下新建一个lib文件夹&#xff0c;存放jar包&#xff0c;因为idea新建modules的时候不是直接创建的web项目&#xff1a; 选中lib点加号把jar导入进去&#xff0c;然后重启tomcat

【转】刨根究底字符编码之四——EASCII及ISO 8859字符编码方案

1. 计算机出现之后&#xff0c;首先逐渐从美国发展到了欧洲。由于欧洲很多国家所用到的字符中&#xff0c;除了基本的、美国也用的那128个ASCII字符之外&#xff0c;还有很多衍生的拉丁字母等字符。比如&#xff0c;在法语中&#xff0c;字母上方有注音符号&#xff1b;而欧洲…

tomcat乱码问题解决

tomcat安装目录下conf文件夹下的logging.properties文件&#xff0c;将java.util.logging.ConsoleHandler.encoding编码为GBK&#xff0c;如图&#xff1a;

【转】HMAC哈希消息认证码及算法原理

HMAC算法原理 HMAC算法是一种基于密钥的报文完整性的验证方法 &#xff0c;其安全性是建立在Hash加密算法基础上的。它要求通信双方共享密钥、约定算法、对报文进行Hash运算&#xff0c;形成固定长度的认证码。通信双方通过认证码的校验来确定报文的合法性。 HMAC算法可以用来…

RestFul风格学习

传统的url是这样的 RestFul是这样的

【转】c#快捷键

CTRL SHIFT B生成解决方案 CTRL F7 生成编译 CTRL O 打开文件 CTRL SHIFT O打开项目 CTRL SHIFT C显示类视图窗口 F4 显示属性窗口 SHIFT F4显示项目属性窗口 CTRL SHIFT E显示资源视图 F12 转到定义 CTRL F12转到声明 CTRL ALT J对象浏览 CTRL ALT …

Angular使用Console.log()打印出来的数据没问题,点击详情后数据变了

我在一个界面添加数据使用updataEvent将对象返回给另一个界面后&#xff0c;在onUpData中处理时使用 this.xxxxx d&#xff0c;直接将地址值给了变量&#xff0c;当这个方法结束后d被重置了&#xff0c;所以this.xxx的值也消失了,这里要使用下面的方法复制一个对象出来。 this…

【转】刨根究底CSS(1):开篇

01 一道小菜 CSS很难&#xff0c;这应该是绝大多数Web开发人员的共识。 什么&#xff1f;你并不觉得很难&#xff1f;那我就先上一道小菜&#xff0c;请君品尝。 这是个乍一看&#xff0c;让人觉得很诡异的案例…… 算了&#xff0c;本来想滔滔不绝介绍一番&#xff0c;但一…

angular8 设置延时时间

延时执行this.setHiden()方法 setTimeout(() > {this.setHiden();},300);

【转】刨根究底CSS(2):CSS中的各种值——初始值,就是默认值吗?

先问个非常简单的问题&#xff0c;这个问题的答案&#xff0c;相信大部分Web开发人员都自认为显而易见&#xff0c;但却又多半会答错&#xff1a;CSS属性中的初始值(initial value)&#xff0c;就是默认值(default value)吗&#xff1f; 难道不对吗&#xff1f;请往下看。 默…

sqlIte 多条件排序失效问题

写倒叙排序就直接按照mysql那样两个字段后面加一个desc&#xff0c;然后一直没有效果&#xff0c;改为如下&#xff1a; order by starttime desc,endtime desc;每个条件后都加desc就可以了&#xff0c;mysql应该是同样适用的&#xff0c;因为多个不同字段可以按照不同的排序方…

【转】刨根究底正则表达式(1):开篇

奇葩的正则表达式 1、常规学习过程很痛苦 计算机领域中有一些非常基础、重要以及应用广泛&#xff0c;但却又特别容易让人困惑、非常难以理解的主题&#xff0c;这包括了字符编码、字节序(即大小端表示)、浮点数实现、日期时间处理以及正则表达式等。 正则表达式目前市面上并…

正则表达式:匹配非0的整数和小数Double

要求可以是整数、小数&#xff0c;但是不能为0 下面正则0.0之类的也是匹配不中的 (后来测试发现出一个bug&#xff0c;竟然可以匹配到1 1&#xff0c;中间加个空格可以匹配中) ^(([1-9][0-9]*.{1}[0-9])|([0].{1}[1-9][0-9]*)|([1-9][0-9]*)|([0][.][0-9][1-9]))$所以又改了一…

【转】刨根究底正则表达式(2):文本查找方式的演化历史

上一篇文章讲到&#xff0c;从根源上来讲&#xff0c;正则表达式是为了解决文本的查找问题(也称为匹配问题)而诞生的。不过&#xff0c;文本查找方式的历史&#xff0c;要远早于正则表达式。 那么&#xff0c;在正则表达式出现之前&#xff0c;文本查找方式经历了什么演化过程…

正则表达式: input框禁止输入空格:不能只有空格、不能有空格、不能为空的判断

1.只有中间和最后能输入空格(如果让最后不能输入空格则把最后一个*改成)&#xff0c;(如果想让开头可以输入空格则把改成*) ^[^\s][\s]*.*$2.不能输入空格 ^[^\s]*$3.如果也不能为空(我是用required来判断的),把*改成 &#xff08;具体我没测试&#xff0c;感觉可以&#xff…

台式机电脑配置单_2020年电脑配置单重点硬件参考

&#xff0c;电脑的基本配件扫盲我前面写过很多&#xff0c;相信很多小伙伴都看过了&#xff0c;没有看过的可以上我专栏参观&#xff1a;电脑神棍局-组装机专栏​www.zhihu.com配置单在本文后面两篇&#xff0c;但是建议前面花两分钟看下。游戏篇后续还有工作和视频工作站篇主…

【转】刨根究底字符编码之五——简体汉字编码方案(GB2312、GBK等)以及全角、半角、CJK

一、概述 1. 英文字母再加一些其他标点字符之类的也不会超过256个&#xff0c;用一个字节来表示一个字符就足够了(2^8 256)。但其他一些文字不止这么多字符&#xff0c;比如中文中的汉字就多达10多万个&#xff0c;一个字节只能表示256个字符&#xff0c;肯定是不够的&#…