目录
一、IO
1.IO的特点
1.服务端阻塞点
server.accept();获取套接字的时候
inputStream.read(bytes);输入流读取数据的时候
2.传统socket是短连接,可以做短连接服务器,他无法做长连接,属于一问一答的模式,比如老的tomcat底层用的就是socket,用完就会关掉线程,因此不会出现线程一直被占用的情况,支持处理多个客户端连接
(1)单线程情况下只能有一个客户端(一个线程维护一个连接,也就是一个socket客户连接)线程一直被占用。
(2)用线程池可以有多个客户端连接,但是非常消耗性能(用此案城池,就是老tomcat原理,只不过是用完后就释放)
原理流程图:
2.基于IO的java网络程序
使用IDEA新建2个java程序:一个作为服务器,另一个作为客户端:
client:
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
public class client {
public static void main(String[] args) throws IOException{
//创建客户端的Socket对象
Socket s=new Socket("192.168.0.178", 50000);//一个可用的地址(server端的)
//获取输出流,写数据
OutputStream os=s.getOutputStream();
os.write("hello,物联网2019级WOOZI".getBytes());
//释放资源
s.close();
}
}
server:
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class sever {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象(SevereSocket)
//ServerSocket (int port)创建绑定到指定端口的服务器套接字
ServerSocket ss=new ServerSocket(50000);
//Socket accept()侦听要连接到此套接字并接受他
Socket s=ss.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is=s.getInputStream();
byte[] bys=new byte[1024];
int len=is.read(bys);
String data=new String(bys,0,len);
System.out.println("接收的数据:"+data);
//释放资源
s.close();
ss.close();
}
}
结果:
二、NIO
1.NIO的简介
主要API介绍:
ServerSocketChannel对应传统IO中的ServerSocket。
SocketChannel对应传统IO中的Socket。
Selector 是NIO核心 ,负载监听 ServerSocketChannel与SocketChannel ,支持单线程连多个客户端;类似通道管理器而且底层是c实现的;线程拥有一个selector就可以支持多个客户端。
SelectionKey 相当于map中的key 相当于记录根据不同动作做不同事情,一个key一个事件。
原理流程图:
NIO的通信步骤:
①创建ServerSocketChannel,为其配置非阻塞模式。
②绑定监听,配置TCP参数,录入backlog大小等。
③创建一个独立的IO线程,用于轮询多路复用器Selector。
④创建Selector,将之前创建的ServerSocketChannel注册到Selector上,并设置监听标识位SelectionKey.OP_ACCEPT。
⑤启动IO线程,在循环体中执行Selector.select()方法,轮询就绪的通道。
⑥当轮询到处于就绪状态的通道时,需要进行操作位判断,如果是ACCEPT状态,说明是新的客户端接入,则调用accept方法接收新的客户端。
⑦设置新接入客户端的一些参数,如非阻塞,并将其继续注册到Selector上,设置监听标识位等。
⑧如果轮询的通道标识位是READ,则进行读取,构造Buffer对象等。
⑨更细节的问题还有数据没发送完成继续发送的问题…
2.基于NIO的java程序
使用IDEA新建2个java程序:一个作为服务器,另一个作为客户端:
client:
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class server {
//网络通信IO操作,TCP协议,针对面向流的监听套接字的可选择通道(一般用于服务端)
private ServerSocketChannel serverSocketChannel;
private Selector selector;
/*
*开启服务端
*/
public void start</