《Java TCP/IP Socket编程》读书笔记(下)

目录

  1. 第四章 进阶
  2. 第五章 NIO
  3. 第六章 深入剖析

第四章 进阶

第五章 NIO

1. Buffer

1.Buffer索引

索引 描述
capacity 缓冲区的元素总数(不可修改)
position 下一个要读/写的元素(从0开始)
limit 第一个不可读/写元素
mark 用户选定position的前一个位置,或0

ByteBuffer#hasRemaining: 当缓冲区至少还有一个元素时,返回true

ByteBuffer#remaining(): 返回剩余元素的个数

2.创建Buffer

  • ByteBuffer#allocate(int capacity) 或 ByteBuffer#allocateDirect(int capacity)
  • ByteBuffer#wrap()方法

Tips:

后援数组:

a) 缓冲区调用array()获取后援数组
b) 调用arrayOffset()获取缓冲区第一个元素在后援数组中的偏移量

direct buffers使用时必须调用isDirect()进行检查

3.存储和接收数据

  • get()/put() –> 绝对位置不会改变position,而相对位置会
  • 允许链式调用
  • Java默认big-endian;ByteOrder#nativeOrder()获取系统支持的字节序列

4.准备Buffer

方法 描述 结果值Position 结果值Limit
clear() 将数据read()/put()进缓冲区 0 capacity
flip() 从缓冲区write()/get() 0 position
rewind() 从缓冲区rewrite()/get() 0 无变化,使mark值无效

5.压缩Buffer的数据

compact()方法将所有未读的数据拷贝到Buffer起始处,然后将position设到最后一个未读元素后面,limit属性依然像clear()方法一样,设置成capacity。这样Buffer准备好写数据,但是不会覆盖未读的数据。

6.Buffer透视

与原始缓冲区共享同一后援存储空间,方法有:duplicate(),slice(),asReadOnlyBuffer(),asReadOnlyBuffer()以及asXXXBuffer();
新缓冲区调用array()还是会返回整个数组,使用isReadOnly()检测是否只读。

7.字符编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Charset charSet = Charset.forName("US-ASCII");
CharsetEncoder encoder = charSet.newEncoder();

encoder.reset();// 非必须

if(encoder.encode(CharBuffer.wrap("input..."), buffer, false) == CoderResult.OVERFLOW){
// ... deal with lack of space in buffer ...
}

...
// 到达输入数据结尾设为 true
if(encoder.encode(CharBuffer.wrap("last input..."), buffer, true) == CoderResult.OVERFLOW){
// ... deal with lack of space in buffer ...
}
encoder.flush(buffer);

2. TCP Channel

  • SocketChannel

    • “包裹”一个基本Java Socket,通过socket()方法进行访问
    • 散射式读/聚集式写 (Scattering read/gathering write)
  • ServerSocketChannel

    • 将信道设置为非阻塞式
    • 测试连接性:
      isConnectionPending() -> finishConnect() -> isConnected()

3. Selector

操作 关键代码
兴趣操作集SelectionKey OP_ACCEPT
OP_CONNECT
OP_READ
OP_WRITE
注册Selector SelectionKey register(Selector sel, int ops)
SelectionKey register(Selector sel, int ops, Object attachment)
SelectionKey 获取和取消 Selector selector()
SelectableChannel channel()
void cancel()
Selector选取和识别就绪的信道 int select()
int select(long timeout)
int selectNow()
Selector wakeup()
int 返回值:准备好的信道总数
Selector获取键集 Set keys() -> 不修改
Set selectedKeys() -> 可修改,需要手动清空
SelectionKey查找就绪的I/O操作 boolean isAcceptable()
boolean isConnectable()
boolean isReadable()
boolean isWritable()
boolean isValid() -> 键是否有效
SelectionKey查找准备就绪的I/O操作 Object attach(Object)
Object attachment()

4. UDP Channel

  • DatagramChannel
操作 关键代码
创建、连接和关闭 static DatagramChannel open()
boolean isOpen()
DatagramSocket socket()
void close()
发送和连接 int send(ByteBuffer src, SocketAddress target)
SocketAddress receive(ByteBuffer dst)
连接DatagramChannel DatagramChannel connect(SocketAddress remote)
read()/write()方法
设置阻塞行为和使用选择器 与SocketChannel和ServerSocketChannel方法一致

第六章 深入剖析