Okio使用分析
来源:互联网 发布:短地址生成算法 编辑:程序博客网 时间:2024/05/21 15:47
最近在研究retrofit的具体实现,retrofit用到了okhttp,okhttp又用到了Okio,so我就想从最底层的Okio开始往上研究。而且一直没有认真看过java的io这个块,也正好趁此机会学习下io相关的知识。
本篇是关于Okio,接下来应该还会写关于okhttp、retrofit各一篇。网上关于这三个框架的文章很多,为什么还要自己在写呢,因为别人的文章看的再多,终究没有自己亲自动手写一篇,从头梳理一遍来的痛快,总是看别人的文章,看后总没有一种通透的感觉,对整个框架似懂非懂的,而且过两天就忘的差不多了,所以很多东西自己写一下很有必要。
本文基于okio-1.9.0分析的,不同版本可能会有差异。如有错误,欢迎留言指正。
先看一张图片(这个不是严格的UML图,算是草稿图吧)
okio的源码其实不多,看了下总共20多个类,大部分类都不是很长。这些类中最核心的类就几个,这几个类就构成了okio的骨架。下面是几个核心的类:
Okio:提供生成Sink和Source的方法
Sink : 接口类,功能上对应OutputStream
Source :接口类,功能上对应InputStream
BufferedSink:接口类继承自Sink,内部有一个Buffer的Sink
BufferedSource:接口类继承自Source,内部有一个Buffer的Source
Buffer:BufferedSink和BufferedSource的最终实现实现类, 实现缓存功能,内部有一个Segment链表
Segment:里面有个byte数组,通过pos,limit控制读写的位置(从byte[]哪里开始读,哪里开始写入),next, prev实现导航到前面或后面的Segment(实现Segment链表结构)
下面是简单的使用方法
socket = new Socket("127.0.0.1", 8080);InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream();BufferedSource source = Okio.buffer(Okio.source(inputStream));BufferedSink sink = Okio.buffer(Okio.sink(outputStream));
平时我们使用socket,有时是直接调用InputStream,OutputStream的方法读写数据,使用Okio后,可以通过InputStream,OutputStream构造出Source,Sink,然后调用Source和Sink提供的方法读写数据。Source和Sink提供了大量的方法读写数据,可以支持字节流和字符流,同时使用Buffer提高了读写效率。
写到这里发现没有写出okio到底好在哪里,以及怎样实现的。这个自己暂时还没有看的很懂,以后看懂了再来写这部分。
下面是一个通过socket实现的通讯例子,分为client和server
Server.java
import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.nio.charset.Charset;import okio.BufferedSink;import okio.BufferedSource;import okio.Okio;/** * Created by lee on 2017/1/24. */public class Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(8080); while (true) { Socket socket = serverSocket.accept(); handleClientSocket(socket); } } catch (IOException e) { e.printStackTrace(); } finally { if (serverSocket != null) { try { serverSocket.close(); } catch (Exception e) { e.printStackTrace(); } } } } private static void handleClientSocket(Socket socket) { Thread thread = new Thread(new Runnable() { @Override public void run() { try { while (true) { BufferedSource source = Okio.buffer(Okio.source(socket)); BufferedSink sink = Okio.buffer(Okio.sink(socket)); int length = source.readInt(); String message = source.readString(length, Charset.forName("utf-8")); System.out.println("length is: " + length + " , message is : " + message); if("error exit".equals(message)){ break; } String responseMsg = getResponseAccordMsg(message); if (responseMsg != null) { int respLength = responseMsg.getBytes().length; sink.writeInt(respLength); sink.writeString(responseMsg, Charset.forName("utf-8")); sink.flush(); } if("error exit".equals(responseMsg)){ break; } } } catch (IOException e) { e.printStackTrace(); }finally { if(socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }); thread.start(); } private static String getResponseAccordMsg(String msg) { String result = ""; if (msg != null && msg.length() > 0) { if (msg.equals("hello")) { result = "hello"; } else if (msg.equals("nice to meet you")) { result = "nice to meet you too"; } else if (msg.equals("see you")) { result = "see you next time"; } } if (result.length() == 0) { result = "error exit"; } return result; }}
client的代码
OkioClient.java
import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.nio.charset.Charset;import okio.BufferedSink;import okio.BufferedSource;import okio.Okio;/** * Created by lee on 2017/1/24. */public class OkioClient { public static void main(String[] args) { Socket socket = null; try { socket = new Socket("127.0.0.1", 8080); InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); BufferedSource source = Okio.buffer(Okio.source(inputStream)); BufferedSink sink = Okio.buffer(Okio.sink(outputStream)); writeMsg(sink, "hello"); while (true) { int length = source.readInt(); String message = source.readString(length, Charset.forName("utf-8")); System.out.println("length is: "+length+" , message is : "+message); if ("error exit".equals(message)) { break; } String respMsg = getResponseAccordMsg(message); writeMsg(sink, respMsg); if ("error exit".equals(respMsg)) { break; } } } catch (IOException e) { e.printStackTrace(); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } private static void writeMsg(BufferedSink sink, String msg) { try { int msgLength = msg.getBytes().length; sink.writeInt(msgLength); sink.writeString(msg, Charset.forName("utf-8")); sink.flush(); } catch (IOException e) { e.printStackTrace(); } } private static String getResponseAccordMsg(String msg) { String result = ""; if (msg != null && msg.length() > 0) { if (msg.equals("hello")) { result = "nice to meet you"; } else if (msg.equals("nice to meet you too")) { result = "see you"; } } if (result.length() == 0) { result = "error exit"; } return result; }}
- Okio使用分析
- okio分析
- OKIO源码分析
- Okio组件源码分析
- Okio源码分析
- Okio框架分析--之一
- Okio库的使用
- Okio库的使用
- Okio框架分析--之二
- okio
- OKIO源码分析<Segment的设计智慧>
- Okio的使用和源码解析
- 在使用okhttp库的时候忘记导入okio
- OkIo介绍
- Android Okio
- 使用okhttp3出现java.lang.NoClassDefFoundError: okio.Buffer的错误怎么办?
- okio源码解析
- Android Okhttp之Okio解析
- Mark一下,以提醒自己
- No manual entry for xxx 错误的解决方案
- Unity发布web版遇到的问题
- 解决textview末尾有时侯会显示不完整表情的问题
- python--导入
- Okio使用分析
- PAT A1031. Hello World for U (20)
- 远程工具——VNC
- 之前的通讯录进行文件保存
- CSS之外层带背景内层左右模式:右侧内容高度自增
- PFSI 开源啦,欢迎您来贡献您的代码
- java面试时遇到的一个有意思的小问题
- 延云YDB对spark广播数据broadcast的Cleaner改进
- Eclipse- Dynamic Web Module 3.0 requires Java 1.6 错误