package cn.com.C;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
public class Client {
public Selector selector;
public SocketChannel socketChannel;
private String name = "";
private static String USER_EXIST = "system message: user exist, please change a name";
private static String USER_CONTENT_SPILIT = "#@#";
private Charset charset = Charset.forName("UTF-8");
public void init(){
try {
selector = Selector.open();
//
socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));
socketChannel.configureBlocking(false);
socketChannel.register(selector,SelectionKey.OP_READ);
new Thread(new ClientThread()).start();
//在主线程中 从键盘读取数据输入到服务器端
Scanner scan = new Scanner(System.in);
while(scan.hasNextLine()){
String line = scan.nextLine();
if("".equals(line)) {
continue; //不允许发空消息
}
if("".equals(name)) {
name = line;
line = name+USER_CONTENT_SPILIT;
} else {
line = name+USER_CONTENT_SPILIT+line;
}
socketChannel.write(charset.encode(line));//sc既能写也能读,这边是写
}
//开辟一个新线程来读取从服务器端的数据
} catch (ClosedChannelException e) {
// TODO Auto-generated catch block
System.out.println("-----");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private class ClientThread implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
int readChannel = selector.select();
if(readChannel == 0){
continue;
}
Set set = selector.selectedKeys();
Iterator iterator = set.iterator();
while(iterator.hasNext()){
SelectionKey sk = (SelectionKey) iterator.next();
iterator.remove();
dealWithSelectionKey(sk);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void dealWithSelectionKey(SelectionKey sk) {
// TODO Auto-generated method stub
if(sk.isReadable()){
try {
SocketChannel sc = (SocketChannel)sk.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
String content = "";
while(sc.read(buffer) > 0){
buffer.flip();
content += charset.decode(buffer);
//若系统发送通知名字已经存在,则需要换个昵称
if(USER_EXIST.equals(content)) {
name = "";
}
System.out.println(content);
sk.interestOps(SelectionKey.OP_READ);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new Client().init();
}
}
package cn.com.C;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
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.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Server {
public Selector selector;
public ServerSocketChannel serverSocketChannel;
public static final int PORT = 9999;
private static String USER_CONTENT_SPILIT = "#@#";
private static String USER_EXIST = "system message: user exist, please change a name";
private static HashSet<String> users = new HashSet<String>();
private static Charset charset = Charset.forName("UTF-8");
public void init(){
try {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(PORT));
//非阻塞模式
serverSocketChannel.configureBlocking(false);
//注册到选择器上,设置为监听状态
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("serverSocketChannel 正在监听......");
while(true){
//查询轮询里面管道注册数
int count = selector.select();
if(count == 0){
continue;
}
System.out.println("====" + count);
Set selectedKeys = selector.selectedKeys();
Iterator iterator = selectedKeys.iterator();
while(iterator.hasNext()){
SelectionKey selectionKey = (SelectionKey) iterator.next();
iterator.remove();
dealWithSelectedKey(serverSocketChannel,selectionKey);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void dealWithSelectedKey(ServerSocketChannel server,SelectionKey sk){
if(sk.isAcceptable()){
try {
SocketChannel socketChannel = server.accept();
//非阻塞模式
socketChannel.configureBlocking(false);
socketChannel.register(selector,SelectionKey.OP_READ);
System.out.println("server 正在监听是否有 client 进来...");
System.out.println(socketChannel.getRemoteAddress());
//设置为监听状态
// sk.interestOps(SelectionKey.OP_ACCEPT);
socketChannel.write(charset.encode("请输入您的名字..."));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//处理客户端
if(sk.isReadable()){
//返回客户端的管道,有数据需要读取
SocketChannel socketChannel = (SocketChannel) sk.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
StringBuilder stringBuilder = new StringBuilder();
try {
while(socketChannel.read(byteBuffer) > 0){
byteBuffer.flip();
stringBuilder.append(charset.decode(byteBuffer));
System.out.println(stringBuilder.length());
}
System.out.println("server 收到的:" +stringBuilder);
sk.interestOps(SelectionKey.OP_READ);
} catch (IOException e) {
System.out.println("错误!!");
sk.cancel();
}finally {
}
//开始注册身份
if(stringBuilder.length() > 0){
String[] content = stringBuilder.toString().split(USER_CONTENT_SPILIT);
if(content != null && content.length ==1) {
String name = content[0];
if(users.contains(name)) {
try {
//名字重复
System.out.println("------+++++++");
socketChannel.write(charset.encode(USER_EXIST));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
users.add(name);
//统计在线人数
int mans = OnlineNum(selector);
System.out.println("------********" + mans);
String message = "欢迎进入聊天室,当前在线人数为:"+mans;
BroadCast(selector, null, message);
}
} else if(content != null && content.length >1){
String name = content[0];
String message = content[1];
message = name + " say " + message;
if(users.contains(name)) {
//不回发给发送此内容的客户端
BroadCast(selector, socketChannel, message);
}
}
}
}
}
public static int OnlineNum(Selector select){
int count = 0;
for(SelectionKey key:select.keys()){
Channel targetChannel = key.channel();
if(targetChannel instanceof SocketChannel){
count++;
}
}
return count;
}
public static void BroadCast(Selector selector, SocketChannel except, String message){
//广播到所有SocketChannel中
for(SelectionKey key:selector.keys()){
Channel targetChannel = key.channel();
if(targetChannel instanceof SocketChannel && targetChannel!=except)
{
SocketChannel dest = (SocketChannel)targetChannel;
try {
//广播
dest.write(charset.encode(message));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
new Server().init();
}
}