服务端代码
import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; 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.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @program: smbTest * @description: * @author: hw * @create: 2020-10-22 15:30 */ public class NIOSServer implements Runnable { private int port = 445; private Charset cs = Charset.forName("gbk"); private ByteBuffer sBuffer = ByteBuffer.allocate(1024); private ByteBuffer rBuffer = ByteBuffer.allocate(1024); private Map<String, SocketChannel> clientsMap = new HashMap<String, SocketChannel>(); private Selector selector; public NIOSServer(int port) { this.port = port; try { init(); } catch (Exception e) { e.printStackTrace(); } } private void init() throws IOException { // 创建ServerSocketChannel通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 设置为非阻塞模式 serverSocketChannel.configureBlocking(false); ServerSocket serverSocket = serverSocketChannel.socket(); // 绑定监听端口 serverSocket.bind(new InetSocketAddress(port)); // 注册选择器,设置选择器选择的操作类型 selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("[SMB] SMB Server starting"); System.out.println("[SMB] Listening for connections on [SMB,TCP-SMB,ALL:" + port + "]"); System.out.println("[SMB] Waiting for new connection ..."); } @Override public void run() { while (true) { try { selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys(); for (SelectionKey key : selectionKeys) { handle(key); } selectionKeys.clear(); } catch (Exception e) { e.printStackTrace(); break; } } } private void handle(SelectionKey selectionKey) throws IOException{ ServerSocketChannel server = null; SocketChannel client = null; String receiveText = null; int count = 0; if (selectionKey.isAcceptable()) { // 通过选择器键获取服务器套接字通道 server = (ServerSocketChannel) selectionKey.channel(); // 通过accept()方法获取套接字通道连接 client = server.accept(); //判断client 是否为空 if (client != null) { // 设置套接字通道为非阻塞模式 client.configureBlocking(false); // 为套接字通道注册选择器,该选择器为服务器套接字通道的选择器,即选择到该SocketChannel的选择器 // 设置选择器关心请求为读操作,设置数据读取的缓冲器容量为处理器初始化时候的缓冲器容量 client.register(selector, SelectionKey.OP_READ); System.out.println("[SMB] Connection from " + client.socket().getRemoteSocketAddress()); } } else if (selectionKey.isReadable()) { // 获取套接字通道 client = (SocketChannel) selectionKey.channel(); rBuffer.clear(); count = client.read(rBuffer); if (count > 0) { rBuffer.flip(); receiveText = String.valueOf(cs.decode(rBuffer).array()); System.out.println("[SMB] "+client.socket().getRemoteSocketAddress() + ":" + receiveText); dispatch(client, receiveText); client = (SocketChannel) selectionKey.channel(); client.register(selector, SelectionKey.OP_READ); } } } private void dispatch(SocketChannel client, String info) throws IOException { Socket s = client.socket(); String name = "[" + s.getInetAddress().toString().substring(1) + ":" + Integer.toHexString(client.hashCode()) + "]"; if (!clientsMap.isEmpty()) { for (Map.Entry<String, SocketChannel> entry : clientsMap.entrySet()) { SocketChannel temp = entry.getValue(); if (!client.equals(temp)) { sBuffer.clear(); sBuffer.put((name + ":" + info).getBytes()); sBuffer.flip(); temp.write(sBuffer); } } } clientsMap.put(name, client); } public static void main(String[] args) { NIOSServer server = new NIOSServer(1445); new Thread(server).start(); NIOClient client = new NIOClient("192.168.120.67",1445); new Thread(client).start(); NIOClient client2 = new NIOClient("192.168.120.67",1445); new Thread(client2).start(); } }
客户端代码
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Date; import java.util.Set; /** * @program: smbTest * @description: * @author: hw * @create: 2020-10-22 16:01 */ public class NIOClient implements Runnable{ private ByteBuffer sBuffer = ByteBuffer.allocate(1024); private ByteBuffer rBuffer = ByteBuffer.allocate(1024); private InetSocketAddress SERVER; private Selector selector; private SocketChannel client; private String receiveText; private String sendText; private int count=0; public NIOClient(String ip, int port){ SERVER = new InetSocketAddress(ip, port); init(); } public void init(){ try { SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); selector = Selector.open(); socketChannel.register(selector, SelectionKey.OP_CONNECT); socketChannel.connect(SERVER); } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { try { while (true) { selector.select(); Set<SelectionKey> keySet = selector.selectedKeys(); for(final SelectionKey key : keySet){ handle(key); } keySet.clear(); } } catch (Exception e) { e.printStackTrace(); } } private void handle(SelectionKey selectionKey) throws IOException{ if (selectionKey.isConnectable()) { client = (SocketChannel) selectionKey.channel(); if (client.isConnectionPending()) { client.finishConnect(); System.out.println("connect success !"); sBuffer.clear(); sBuffer.put((new Date()+" connected!").getBytes()); sBuffer.flip(); client.write(sBuffer); //启动线程监听控制台输入并发送到客户端 new Thread(){ @Override public void run() { while(true){ try { sBuffer.clear(); InputStreamReader input = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(input); sendText = br.readLine(); sBuffer.put(sendText.getBytes()); sBuffer.flip(); client.write(sBuffer); } catch (IOException e) { e.printStackTrace(); break; } } } }.start(); } client.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { client = (SocketChannel) selectionKey.channel(); rBuffer.clear(); count=client.read(rBuffer); if(count>0){ receiveText = new String( rBuffer.array(),0,count); System.out.println(receiveText); client = (SocketChannel) selectionKey.channel(); client.register(selector, SelectionKey.OP_READ); } } } public static void main(String args[]){ NIOClient client = new NIOClient("192.168.120.67",1445); new Thread(client).start(); } }