- NIO学习笔记
- 关于 selector , ServerSocketChannel 网络编程的使用
编写服务端
package src.com.NIO.groupchart;
import javax.xml.soap.SOAPElementFactory;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class NioServer {
private Selector selector;
private ServerSocketChannel serverSocketChannel;
private final int port = 6666;
/**
* 初始化 server
* @throws IOException
*/
public NioServer() throws IOException {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(port));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector , SelectionKey.OP_ACCEPT);
}
/**
* 创建 服务端
*/
public void listen() {
System.out.println("监听线程 : " + Thread.currentThread().getName());
try{
// 循环处理连接请求
while (true) {
int count = selector.select();
if (count > 0 ) {
// 获取连接 的 selector 集合
Iterator<SelectionKey> selectKeys = selector.selectedKeys().iterator();
while (selectKeys.hasNext()) {
SelectionKey key = selectKeys.next();
// 监听连接请求
if (key.isAcceptable()) {
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector , SelectionKey.OP_READ);
// 提示
System.out.println(socketChannel.getRemoteAddress() + ": 上线");
}
if (key.isReadable()) {
// 处理读请求
readData(key);
}
selectKeys.remove();
}
}
}
}catch (Exception e) {
}
}
/**
* 读取数据请求的数据
* @param key
*/
private void readData(SelectionKey key) {
// 读取到关联的socketChannel
SocketChannel socketChannel = null;
try{
socketChannel = (SocketChannel) key.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int count = socketChannel.read(byteBuffer);
if (count>0) {
// 把缓冲区的数据读取成字符串
String msg = new String(byteBuffer.array());
System.out.println("读取到的数据 " + msg);
// 向其他客户端发送消息
sendMsgToOtherCilents(msg ,socketChannel);
}
System.out.println();
}catch (Exception e) {
e.printStackTrace();
try{
System.out.println(socketChannel.getRemoteAddress() + "离线了....");
// 取消注册
key.cancel();
// 关闭通道
serverSocketChannel.close();
}catch (Exception ex) {
ex.printStackTrace();
}
}
}
/**
* 向其他客户端发送消息
* @param msg
* @param socketChannel
*/
private void sendMsgToOtherCilents(String msg, SocketChannel socketChannel) throws IOException {
System.out.println("消息转发给 : " +Thread.currentThread().getName());
for (SelectionKey selectionKey : selector.keys()) {
SelectableChannel channel = selectionKey.channel();
if (channel instanceof SocketChannel && channel != socketChannel) {
// 将channle 强转为
SocketChannel returnChannel = (SocketChannel) channel;
ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());
returnChannel.write(byteBuffer);
}
}
}
// 创建服务器对象
public static void main(String[] args) throws IOException {
NioServer nioServer = new NioServer();
nioServer.listen();
}
}
- 客户端的 创建
package src.com.NIO.groupchart;
import java.io.IOException;
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.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Scanner;
/**
* nio 客户端
*/
public class NioCilent {
private final String HOST = "127.0.0.1" ;
private Selector selector;
private SocketChannel socketChannel;
private String username;
private final int port = 6666;
public NioCilent() throws IOException {
selector = Selector.open();
socketChannel = SocketChannel.open(new InetSocketAddress(HOST , port));
socketChannel.configureBlocking(false);
// 将channel 组测到 select
socketChannel.register(selector , SelectionKey.OP_READ);
username = socketChannel.getLocalAddress().toString().substring(1);
}
/**
* 推送信息
* @param info
*/
public void sendInfo(String info) {
info = username + ": say " + info;
try {
socketChannel.write(ByteBuffer.wrap(info.getBytes(StandardCharsets.UTF_8)));
}catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读取信息
*/
public void readInfo() {
try{
int count = selector.select();
if (count > 0) {
Iterator<SelectionKey> iterators = selector.selectedKeys().iterator();
while (iterators.hasNext()) {
SelectionKey key = iterators.next();
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
channel.read(byteBuffer);
// 把读到的 缓冲区读取到
String str = new String(byteBuffer.array());
System.out.println(str.trim());
iterators.remove();
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
NioCilent nioCilent = new NioCilent();
new Thread() {
@Override
public void run() {
while (true) {
nioCilent.readInfo();;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}.start();
//发送数据给服务器端
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String s = scanner.nextLine();
nioCilent.sendInfo(s);
}
}
}