电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

Java ByteBuffer網(wǎng)絡(luò)編程用法實(shí)例解析

瀏覽:7日期:2022-08-22 11:11:24

做tcp網(wǎng)絡(luò)編程,要解析一批批的數(shù)據(jù),可是數(shù)據(jù)是通過Socket連接的InputStream一次次讀取的,讀取到的不是需要轉(zhuǎn)換的對象,而是要直接根據(jù)字節(jié)流和協(xié)議來生成自己的數(shù)據(jù)對象。

按照之前的編程思維,總是請求然后響應(yīng),當(dāng)然Socket也是請求和響應(yīng),不過與單純的請求響應(yīng)是不同的。

這里Socket連接往往是要保持住的,也就是長連接,然后設(shè)置一個(gè)緩沖區(qū),網(wǎng)絡(luò)流不斷的追加到緩沖區(qū)。然后后臺(tái)去解析緩沖區(qū)的字節(jié)流。

Java ByteBuffer網(wǎng)絡(luò)編程用法實(shí)例解析

如圖所示,網(wǎng)絡(luò)的流一直在傳遞,我們收到也許是完成的數(shù)據(jù)流,也可能是沒有傳遞完的。這里就需要監(jiān)視管道,不斷讀取管道中的流數(shù)據(jù),然后向緩沖區(qū)追加。程序從頭開始解析,如果目前緩沖區(qū)包含了數(shù)據(jù),則解析,沒有則放棄繼續(xù)讀取管道流。

就算管道中包含了數(shù)據(jù),也不一定包含了完成的數(shù)據(jù)。例如,100個(gè)字節(jié)是一個(gè)數(shù)據(jù)體,可是目前緩沖區(qū)內(nèi)包含了120個(gè)字節(jié),這就是說緩沖區(qū)包含了一條數(shù)據(jù),但是還有沒有傳遞完的字節(jié)流。那么就要把前100個(gè)字節(jié)拿出來解析,然后從緩沖區(qū)清除這100個(gè)字節(jié)。那緩沖區(qū)就剩下20個(gè)字節(jié)了,這些數(shù)據(jù)可能在下次流中補(bǔ)充完成。

如何建立緩沖?

/** * 全局MVB數(shù)據(jù)緩沖區(qū) 占用 1M 內(nèi)存 */ private static ByteBuffer bbuf = ByteBuffer.allocate(10240); /** * 線程安全的取得緩沖變量 */ public static synchronized ByteBuffer getByteBuffer() { return bbuf; }

寫一個(gè)Socket客戶端,該客戶端得到Socket連接,然后讀取流,一直向緩沖中追加字節(jié)流,每次追加后調(diào)用一個(gè)方法來解析該流

public void run() { Socket socket = GlobalClientKeep.mvbSocket; if (null != socket) { try { // 獲得mvb連接引用 OutputStream ops = socket.getOutputStream(); InputStream ips = socket.getInputStream(); while (true) { if (null != ops && null != ips) { // 接收返回信息 byte[] bt = StreamTool.inputStreamToByte(ips); ByteBuffer bbuf = GlobalCommonObjectKeep.getByteBuffer(); // 設(shè)置到緩沖區(qū)中 bbuf.put(bt); // //////////////////////////////////////////////////////////////////////// // 拆包解析方法 splitByte(ops); ops.flush(); } } } catch (Exception e) { e.printStackTrace(); } } else { // 如果連接存在問題,則必須重新建立 GlobalClientKeep.initMvbSocket(); } }

關(guān)于如何讀取流,我有一篇博客專門講解了所以這里是直接調(diào)用方法

byte[] bt = StreamTool.inputStreamToByte(ips);

那么解析方法是如何做的?

解析方法首先獲得該緩沖中的所有可用字節(jié),然后判斷是否符合一條數(shù)據(jù)條件,符合就解析。如果符合兩條數(shù)據(jù)條件,則遞歸調(diào)用自己。其中每次解析一條數(shù)據(jù)以后,要從緩沖區(qū)中清除已經(jīng)讀取的字節(jié)信息。

/** * @說明 拆包解析方法 */ public static void splitByte(OutputStream ops) { try { ByteBuffer bbuf = GlobalCommonObjectKeep.getByteBuffer(); int p = bbuf.position(); int l = bbuf.limit(); // 回繞緩沖區(qū) 一是將 curPointer 移到 0, 二是將 endPointer 移到有效數(shù)據(jù)結(jié)尾 bbuf.flip(); byte[] byten = new byte[bbuf.limit()]; // 可用的字節(jié)數(shù)量 bbuf.get(byten, bbuf.position(), bbuf.limit()); // 得到目前為止緩沖區(qū)所有的數(shù)據(jù) // 進(jìn)行基本檢查,保證已經(jīng)包含了一組數(shù)據(jù) if (checkByte(byten)) { byte[] len = new byte[4]; // 數(shù)組源,數(shù)組源拷貝的開始位子,目標(biāo),目標(biāo)填寫的開始位子,拷貝的長度 System.arraycopy(byten, 0, len, 0, 4); int length = StreamTool.bytesToInt(len); // 每個(gè)字節(jié)流的最開始肯定是定義本條數(shù)據(jù)的長度 byte[] deco = new byte[length]; // deco 就是這條數(shù)據(jù)體 System.arraycopy(byten, 0, deco, 0, length); // 判斷消息類型,這個(gè)應(yīng)該是從 deco 中解析了,但是下面具體的解析內(nèi)容不再?? int type = 0; // 判斷類型分類操作 if (type == 1) {} else if (type == 2) {} else if (type == 3) {} else { System.out.println('未知的消息類型,解析結(jié)束!'); // 清空緩存 bbuf.clear(); } // 如果字節(jié)流是多余一組數(shù)據(jù)則遞歸 if (byten.length > length) { byte[] temp = new byte[bbuf.limit() - length]; // 數(shù)組源,數(shù)組源拷貝的開始位子,目標(biāo),目標(biāo)填寫的開始位子,拷貝的長度 System.arraycopy(byten, length, temp, 0, bbuf.limit() - length); // 情況緩存 bbuf.clear(); // 重新定義緩存 bbuf.put(temp); // 遞歸回調(diào) splitByte(ops); }else if(byten.length == length){ // 如果只有一條數(shù)據(jù),則直接重置緩沖就可以了 // 清空緩存 bbuf.clear(); } } else { // 如果沒有符合格式包含數(shù)據(jù),則還原緩沖變量屬性 bbuf.position(p); bbuf.limit(l); } } catch (Exception e) { e.printStackTrace(); } }

代碼只是一個(gè)參考,主要講解如何分解緩沖區(qū),和取得緩沖區(qū)的一條數(shù)據(jù),然后清除該數(shù)據(jù)原來站的空間。

至于緩沖區(qū)的屬性,如何得到緩沖區(qū)的數(shù)據(jù),為什么要清空,bbuf.flip();是什么意思。下面來說一下關(guān)于ByteBuffer 的一下事情。

ByteBuffer 中有幾個(gè)屬性,其中有兩個(gè)很重要。limit和 position。position開始在0,填充數(shù)據(jù)后等于數(shù)據(jù)的長度,而limit是整個(gè)緩沖可用的長度。bbuf.flip();之后,position直接變?yōu)?,而limit直接等于position。JDK源碼如下:

/** * Flips this buffer. The limit is set to the current position and then * the position is set to zero. If the mark is defined then it is * discarded. * * <p> After a sequence of channel-read or <i>put</i> operations, invoke * this method to prepare for a sequence of channel-write or relative * <i>get</i> operations. For example: * * <blockquote><pre> * buf.put(magic); // Prepend header * in.read(buf); // Read data into rest of buffer * buf.flip(); // Flip buffer * out.write(buf); // Write header + data to channel</pre></blockquote> * * <p> This method is often used in conjunction with the {@link * java.nio.ByteBuffer#compact compact} method when transferring data from * one place to another. </p> * * @return This buffer */ public final Buffer flip() {limit = position;position = 0;mark = -1;return this; }

這樣,在position和limit之間的數(shù)據(jù)就是我們要的可用數(shù)據(jù)。

但是position和limit是ByteBuffer在put和get時(shí)需要的屬性,所以在使用后要么還原,要么像上面代碼一樣,清除一些字節(jié)信息然后重置。

ByteBuffer 的get和put不是我們平常的取值和設(shè)值一樣,他會(huì)操縱一些屬性變化。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 防水接头-电缆防水接头-金属-电缆密封接头-不锈钢电缆接头 | led全彩屏-室内|学校|展厅|p3|户外|会议室|圆柱|p2.5LED显示屏-LED显示屏价格-LED互动地砖屏_蕙宇屏科技 | 石英砂矿石色选机_履带辣椒色选机_X光异物检测机-合肥幼狮光电科技 | 外贸网站建设-外贸网站设计制作开发公司-外贸独立站建设【企术】 | 门禁卡_智能IC卡_滴胶卡制作_硅胶腕带-卡立方rfid定制厂家 | 海鲜池-专注海鲜鱼缸、移动海鲜缸、饭店鱼缸设计定做-日晟水族厂家 | 直流电能表-充电桩电能表-导轨式电能表-智能电能表-浙江科为电气有限公司 | 闭端端子|弹簧螺式接线头|防水接线头|插线式接线头|端子台|电源线扣+护线套|印刷电路板型端子台|金笔电子代理商-上海拓胜电气有限公司 | 活性氧化铝|无烟煤滤料|活性氧化铝厂家|锰砂滤料厂家-河南新泰净水材料有限公司 | 在线浊度仪_悬浮物污泥浓度计_超声波泥位计_污泥界面仪_泥水界面仪-无锡蓝拓仪表科技有限公司 | 意大利Frascold/富士豪压缩机_富士豪半封闭压缩机_富士豪活塞压缩机_富士豪螺杆压缩机 | 国标白水泥,高标号白水泥,白水泥厂家-淄博华雪建材有限公司 | 合肥卓创建筑装饰,专业办公室装饰、商业空间装修与设计。 | 石膏基自流平砂浆厂家-高强石膏基保温隔声自流平-轻质抹灰石膏粉砂浆批发-永康市汇利建设有限公司 | bng防爆挠性连接管-定做金属防爆挠性管-依客思防爆科技 | 泰安办公家具-泰安派格办公用品有限公司| 德国EA可编程直流电源_电子负载,中国台湾固纬直流电源_交流电源-苏州展文电子科技有限公司 | 法兰螺母 - 不锈钢螺母制造厂家 - 万千紧固件--螺母街 | 淬火设备-钎焊机-熔炼炉-中频炉-锻造炉-感应加热电源-退火机-热处理设备-优造节能 | RTO换向阀_VOC高温阀门_加热炉切断阀_双偏心软密封蝶阀_煤气蝶阀_提升阀-湖北霍科德阀门有限公司 | 水冷散热器_水冷电子散热器_大功率散热器_水冷板散热器厂家-河源市恒光辉散热器有限公司 | DAIKIN电磁阀-意大利ATOS电磁阀-上海乾拓贸易有限公司 | 博客-悦享汽车品质生活| 精密五金冲压件_深圳五金冲压厂_钣金加工厂_五金模具加工-诚瑞丰科技股份有限公司 | 定制/定做冲锋衣厂家/公司-订做/订制冲锋衣价格/费用-北京圣达信 | 聚氨酯保温钢管_聚氨酯直埋保温管道_聚氨酯发泡保温管厂家-沧州万荣防腐保温管道有限公司 | 台湾阳明固态继电器-奥托尼克斯光电传感器-接近开关-温控器-光纤传感器-编码器一级代理商江苏用之宜电气 | 电磁铁_推拉电磁铁_机械手电磁吸盘电磁铁厂家-广州思德隆电子公司 | 德国EA可编程直流电源_电子负载,中国台湾固纬直流电源_交流电源-苏州展文电子科技有限公司 | 达利园物流科技集团-| 乐考网-银行从业_基金从业资格考试_初级/中级会计报名时间_中级经济师 | 间苯二酚,间苯二酚厂家-淄博双和化工 | 北京律师事务所_房屋拆迁律师_24小时免费法律咨询_云合专业律师网 | 心得体会网_心得体会格式范文模板| 挖掘机挖斗和铲斗生产厂家选择徐州崛起机械制造有限公司 | 卡诺亚轻高定官网_卧室系统_整家定制_定制家居_高端定制_全屋定制加盟_定制家具加盟_定制衣柜加盟 | 今日热点_实时热点_奇闻异事_趣闻趣事_灵异事件 - 奇闻事件 | 超声波破碎仪-均质乳化机(供应杭州,上海,北京,广州,深圳,成都等地)-上海沪析实业有限公司 | 污水/卧式/潜水/钻井/矿用/大型/小型/泥浆泵,价格,参数,型号,厂家 - 安平县鼎千泵业制造厂 | 胜为光纤光缆_光纤跳线_单模尾纤_光纤收发器_ODF光纤配线架厂家直销_北京睿创胜为科技有限公司 - 北京睿创胜为科技有限公司 | 油冷式_微型_TDY电动滚筒_外装_外置式电动滚筒厂家-淄博秉泓机械有限公司 |