TCP分析
accept方法是阻塞的,作用就是等待客户端连接
客户端创建对象并连接服务器,此时是通过三次握手协议保证跟服务器之间的连接
针对客户端来说,是往外写的,所以是输出流
正对服务器来说,是往里读的,所以是输入流
read方法也是阻塞的
在关流的时候,还多了一个往服务器写结束标记的动作
最后一步断开连接,通过四次挥手协议保证连接终止
三次握手协议(三次连接)
简单介绍
第一次:客户端向服务器发出连接请求,等待服务器确认
第二次:服务器向客户端返回一个响应,告诉客户端收到了请求
第三次:客户端再次发出确认信息,连接确定
四次挥手
简单介绍
第一次:客户端向服务器发出取消连接请求
第二次:服务器向客户端返回一个响应,表示收到客户端取消请求并且服务器最后数据处理完毕
第三次:服务器向客户端发出确认取消信息
第四次:客户端再次发送确认信息,连接取消
初步了解NIO
之前学习的IO称之为BIO:BIO(Blocking IO) 阻塞型IO
NIO(No Blocking IO) 非阻塞型IO
好处:不需要一直等待,当一切就绪,再去做
BIO和NIO的区别
BIO是阻塞的,NIO是非阻塞的
BIO是面向流的,NIO是面向缓冲区的
BIO中数据传输是单向的,NIO的数据传输是双向的
NIO的三大模块
第一个模块,缓冲区用来存储数据的
第二个模块,通道建立连接,并传输缓冲区的
第三个模块,选择器,用来监视通道的
NIO之缓冲区
实际就是一个数组 Buffer
有七个子类 ByteBuffer ShortBuffer IntBuffer LongBuffer FloatBuffer DoubleBuffer CharBuffer
最常用的:ByteBuffer
static ByteBuffer allocate(长度) 创建byte类型的缓冲区
static ByteBuffer wrap(byte[] array) 创建一个有内容的byte类型缓冲区
public class ByteBufferTest {
public static void main(String[] args) {
ByteBuffer allocate1 = ByteBuffer.allocate(5);
//get 方法 一次获取一个字节
for (int i = 0; i < 5; i++) {
System.out.println(allocate1.get());
}
}
}
public class ByteBufferTest {
public static void main(String[] args) {
byte[] bytes={97,98,99};
ByteBuffer wrap = ByteBuffer.wrap(bytes);
//缓冲区长度为3
//缓冲区的内容就是字节数组的内容
for (int i = 0; i < 3; i++) {
System.out.println(wrap.get());
}
}
}
创建有内容的缓冲区
public class ByteBufferTest {
public static void main(String[] args) {
ByteBuffer bb=ByteBuffer.wrap("aaa".getBytes());
for (int i = 0; i < 3; i++) {
System.out.println(bb.get(i));
}
}
}
缓冲区的两个功能读/写
把数据写入缓冲区中 使用缓冲区读的功能
把缓冲区的数据读取并打印出来 使用缓冲区读的功能
必须站在缓冲区的角度去想
capacity :容量(长度)
limit:界限(最多能读/写到哪里)
posotion:位置(读/写那个索引)
int position() 当前要操作的索引
int limit() 最多能操作到那个索引
int capacity() 缓冲区总长度
int remaining() 还有多少能操作
put(byte b) 一次添加一个字节
public class test {
public static void main(String[] args) {
ByteBuffer bb=ByteBuffer.allocate(10);
System.out.println(bb.position());//0
System.out.println(bb.limit());//10
System.out.println(bb.capacity());//10
//一次添加一个字节
bb.put((byte) 97);
//一次添加一个字节数组
bb.put("aaa".getBytes());
//修改position
bb.position(1);
//修改limit
bb.limit(5);
System.out.println(bb.remaining());
System.out.println(bb.hasRemaining());
}
}
获取缓冲区中的数据
flip() 切换读写模式
get() 读一个字节
get(byte[] dst)读多个字节
get(int index)读指定索引的字节
rewind() 将position设置为0,可重复读
clear() 数据读写完毕(读-》写)
array() 将缓冲区转换成字节数组返回
public class test1 {
public static void main(String[] args) {
ByteBuffer bb=ByteBuffer.allocate(10);
bb.put("aczxcsad".getBytes());
//flip 读写切换模式
bb.flip();
//get()读一个字节
// while (bb.limit()!=bb.position()){
// System.out.println((char) bb.get());
// }
for (int i = 0; i < bb.limit(); i++) {
System.out.println((char) bb.get());
}
//get(byte[] dst) 读多个字节
byte[] bytes=new byte[bb.limit()];
ByteBuffer byteBuffer = bb.get(bytes);
System.out.println(byteBuffer.toString());
//get(int index) 读指定索引的字节
System.out.println(bb.get(0));
//rewind 将position设置为0 可以重复读
ByteBuffer rewind = bb.rewind();
for (int i = 0; i < bb.limit(); i++) {
System.out.println((char) bb.get());
}
//clear 数据读写完毕
bb.clear();
bb.put("wqeqe".getBytes());
//array 将缓冲区转换称字节数组返回
byte[] array = bb.array();
System.out.println(new String(array));
}
}
小结:
数据写入缓冲区中,数据是从外边进来的,所以在进行读的操作
数据写入缓冲区中,数据是从缓冲区里面到外边的,所以在进行写的操作
获得缓冲区的数据之前,需要调用filp方法
再次写数据之前,需要调用clear方法