1.先谈OIO
传统的socket的方式。在server.acept()和is.read()处会发生阻塞,在单线程情况下,只能有一个客户端对应服务端访问。
代码实现:
1.创建服务端服务
2.服务运行,在指定接口监听
3.当有请求达到时,接收客户端请求
4.处理请求
package IO;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class OIO {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
try {
// ServerSocket在10101端口监听
ServerSocket server = new ServerSocket(10101);
System.out.println("连接到服务器");
while (true) {
// 从端口监听到socket并获取到socket对象
Socket accept = server.accept();
// 处理socket消息
executorService.execute(new Runnable() {
@Override
public void run() {
// 多线程情况下监听
// TODO Auto-generated method stub
try {
handler(accept);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void handler(Socket accept) throws IOException {
// TODO Auto-generated method stub
// 读socket里封装的字节流信息
InputStream is = accept.getInputStream();
// 创建字节数组
byte[] by = new byte[1024];
//
while (true) {
//
int len = is.read(by);
// 如果不是最后一个字节
if (len != -1) {
System.out.println(new String(by, 0, len));
}
}
}
}
采用多线程可实现多个服务端访问,但是耗费资源。
NIO.非阻塞式IO
代码实现思路
1.初始化服务 服务对应有端口
1.1创建一个socketServer通道,并初始化通道(设置非阻塞,通道绑定端口)
1.2创建一个通道管理者。绑定到对应的通道。并设置SelectionKey.OP_ACCEPT事件(这个事件设置完成后,管理者会返回)
initServer(int port)
2.服务监听。
3.请求处理
3.1:处理连接请求。
3.2:处理读的请求。
package NIO;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class NIOServer {
private Selector selector;
//1.初始化服务
public void initServer(int port) throws IOException
{
//1.先获得一个通道
ServerSocketChannel socketChannel = ServerSocketChannel.open();
// 设置非阻塞
socketChannel.configureBlocking(false);
//将通道绑定到对应端口
socketChannel.socket().bind(new InetSocketAddress(port));
//2.获得一个通道管理器
selector = Selector.open();
//3.注册绑定通道和通道管理器
// SelectionKey.OP_ACCEPT 当事件到达时,通道管理器会返回,否则一直阻塞
socketChannel.register(selector, SelectionKey.OP_ACCEPT);
}
//2.请求监听
public void serverlisten() throws IOException{
//无限循环监听
while(true)
{//监听到事件到达,返回
selector.select();
//使用迭代器轮询监听
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext())
{
//先获取selectionKey
SelectionKey selectionKey = iterator.next();
// 再移除已经访问的
iterator.remove();
//根据selectionKey来处理请求
handler(selectionKey);
}
}
}
3.处理请求
public void handler(SelectionKey key) throws IOException {
// 3.1:处理接受请求
if(key.isAcceptable())
{//允许接受的则先处理接收请求
//提取通道信息
ServerSocketChannel server = (ServerSocketChannel) key.channel();
//获取客户端连接通道
SocketChannel channel = server.accept();
channel.configureBlocking(false);//设置非阻塞
//设置读权限
channel.register(selector, SelectionKey.OP_READ);
}
if(key.isReadable()) {
// 3.2:处理读请求
//
SocketChannel channel = (SocketChannel) key.channel();
//创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = channel.read(buffer);
//if
if(read>0)
{
//
byte[] bs = buffer.array();
String msg=new String(bs);
System.out.println("收到消息:"+msg);
ByteBuffer src=ByteBuffer.wrap(bs);
channel.write(src);
}
else {
System.out.println("没有服务,已关闭");
key.cancel();
}
}
}
//
public static void main(String[] args) throws IOException {
NIOServer nIOServer=new NIOServer();
nIOServer.initServer(10101);
nIOServer.serverlisten();
}
}