通过NIO的学习,自己简单写了一个,C/S架构的聊天工具。
Server端:
1.接受客户端Channel。
2.记录客户端集合clients。利用channel进行区分客户端,后续可以添加一个ID。
3.客户端通过遍历clients,对除发送者以外的所有客户端通讯。
Client端:
1.发送请求。
2.接收内容
3.获取控制台内容,并发送
待解决问题:
由于获取控制台数据的流,System.in是阻塞的IO:
ReadableByteChannel in=Channels.newChannel(System.in);
ByteBuffer buffer = ByteBuffer.allocate(1024);
in.read(buffer);//这里会阻塞
所以每次接收消息的话,并需控制台触发一下,不知道有没有好的方法,还请知道的大牛指导下,谢谢
以下是代码:
public class NioServer {
private static Set<SocketChannel> clients=new HashSet<SocketChannel>();
public static void main(String[] args) {
ServerSocketChannel serverChannel;
Selector selector;
try{
//服务端的准备
serverChannel= ServerSocketChannel.open();
ServerSocket serverSocket=serverChannel.socket();
serverSocket.bind(new InetSocketAddress(12345));
serverChannel.configureBlocking(false);
selector=Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e){
e.printStackTrace();
return;
}
while(true){
try {
selector.select();
System.out.println("======select========");
} catch (IOException e) {
e.printStackTrace();
break;
}
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()){
SelectionKey key=iterator.next();
iterator.remove();
try {
if(key.isAcceptable()){
System.out.println("=============accept============");
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client=server.accept();//接受客户端的请求
client.configureBlocking(false);//客户端 服务端 全都设置为 非阻塞
clients.add(client);
client.register(key.selector(), SelectionKey.OP_READ);
}
if(key.isReadable()){
System.out.println("=============read==============="+clients);
SocketChannel client=(SocketChannel) key.channel();
ByteBuffer buffer=ByteBuffer.allocate(1024);
if(client.read(buffer)>0){
Iterator<SocketChannel> it=clients.iterator();
while(it.hasNext()){
SocketChannel other=it.next();
if(other != client){
buffer.flip();
other.write(buffer);
}
}
}
key.interestOps(SelectionKey.OP_READ);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
private String name="A";
public void execute(){
try {
SocketChannel client = SocketChannel.open();
Selector selector = Selector.open();
client.configureBlocking(false);
client.connect(new InetSocketAddress("127.0.0.1", 12345));
//注册监听Connect
client.register(selector, SelectionKey.OP_CONNECT,name);
while(true){
int n = selector.select();
if(n==0){
continue;
}
Iterator<SelectionKey> iterator=selector.selectedKeys().iterator();
while(iterator.hasNext()){
SelectionKey key=iterator.next();
iterator.remove();
if(key.isConnectable() && client.finishConnect()){
System.out.println("[client]:连接成功");
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put(name.getBytes());
buffer.flip();
client.write(buffer);
key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
}
if(key.isReadable()){
System.out.println("[client]:开始接受");
ByteBuffer buffer = ByteBuffer.allocate(1024);
WritableByteChannel out = Channels.newChannel(System.out);
while(client.read(buffer)>0){
System.out.println("==============");
buffer.flip();
out.write(buffer);
}
key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
}
if(key.isWritable()){
ReadableByteChannel in=Channels.newChannel(System.in);
ByteBuffer buffer = ByteBuffer.allocate(1024);
if(in.read(buffer)>0){
buffer.flip();
SocketChannel channel = (SocketChannel) key.channel();
channel.write(buffer);
buffer.clear();
}
key.interestOps(SelectionKey.OP_READ);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}