Netty线程模型
传统io模型
-
采用阻塞io获取数据
-
每个链接都需要独立的线程去完成数据输入或处理,
存在的问题 -
并发数很大的话会占用很多线程资源并且线程切换也需要消耗很多
-
连接成功后如果当前线程没有数据可读该线程会阻塞在read操作造成资源浪费
reactor模型
- 基于一个或多个客户端输入同时传递给服务器处理的模式
- 服务端处理多个请求并且将请求分发给线程池去处理,reactor模式也叫做dispatcher模式
- reactor模式基于io复用监听事件,收到事件后分发给线程;
三种实现模式
- 单Reactor单线程
- 单Reactor多线程
- 主从Reactor多线程 -》演变成netty
单Reactor单线程
package com.fr.server.groupchat;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
public class GroupServer {
private ServerSocketChannel listenchanel;
private final int port=6666;
private Selector selector;
public GroupServer() throws IOException {
listenchanel=ServerSocketChannel.open();
selector=Selector.open();
listenchanel.configureBlocking(false);
listenchanel.socket().bind(new InetSocketAddress(port));
listenchanel.register(selector, SelectionKey.OP_ACCEPT);
}
public static void main(String[] args) throws IOException {
GroupServer groupServer=new GroupServer();
groupServer.listen();
}
public void listen() throws IOException {
while (true){
int select = selector.select();
if (select>0){
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey next = iterator.next();
if (next.isAcceptable()){
SocketChannel accept = listenchanel.accept();
accept.configureBlocking(false);
accept.register(selector,SelectionKey.OP_READ);
System.out.println(accept.getRemoteAddress()+"上线了");
}
if(next.isReadable()){
readData(next);
}
iterator.remove();
}
}else {
System.out.println("等待");
}
}
}
private void sendInfoToOtherClient(String msg,SocketChannel channel) throws IOException {
System.out.println("转发消息");
for (SelectionKey key:selector.keys()){
Channel target = key.channel();
if (target instanceof SocketChannel && target!=channel)
{
SocketChannel socketChannel=(SocketChannel)channel;
ByteBuffer byteBuffer=ByteBuffer.wrap(msg.getBytes());
socketChannel.write(byteBuffer);
}
}
}
private void readData(SelectionKey next) {
SocketChannel channel = (SocketChannel) next.channel();
try {
ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
int read=channel.read(byteBuffer);
if (read>0) {
String msg=new String(byteBuffer.array());
sendInfoToOtherClient(msg,channel);
System.out.println(msg+"客户端收到数据");
}
}catch (IOException e){
try {
System.out.println(channel.getRemoteAddress()+"离线了");
next.cancel();
channel.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}finally {
}
}
}
客户端就不写了,这个简单的Nioserver 就是reactor单线程模式。
存在问题
并发存在问题。
单reactor多线程
问题