服务端:
package com.songguo.GroupChat;
import java.io.IOError;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
public class ChatServer {
//定义属性
private Selector selector;
private ServerSocketChannel listenChannel;
private static final int PORT=8080;
//构造器
public ChatServer(){
try {
//得到选择器
selector=Selector.open();
//ServerSocketChannel
listenChannel=ServerSocketChannel.open();
//绑定端口
listenChannel.socket().bind(new InetSocketAddress(PORT));
listenChannel.configureBlocking(false);
listenChannel.register(selector,SelectionKey.OP_ACCEPT);
}catch (IOException e){
e.printStackTrace();
}
}
public void listen(){
try {
while(true){
int count = selector.select();
if(count>0){
//有事件要处理
Iterator<SelectionKey> selectionKeyIterator = selector.selectedKeys().iterator();
while(selectionKeyIterator.hasNext()){
SelectionKey key=selectionKeyIterator.next();
if(key.isAcceptable()){
SocketChannel socketChannel = listenChannel.accept();
socketChannel.configureBlocking(false);
//将该sc注册到selector
socketChannel.register(selector,SelectionKey.OP_READ);
//提示
System.out.println(socketChannel.getRemoteAddress()+"上线");
}
if(key.isReadable()){//通道可读
//处理读
read(key);
}
//删除当前key防止重复操作
selectionKeyIterator.remove();
}
}else{
System.out.println("等待中");
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
}
}
//读取消息
private void read(SelectionKey key){
//定义一个socketchannel
SocketChannel channel=null;
try {
channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = channel.read(buffer);
if(read>0){
String msg = new String(buffer.array());
System.out.println("from 客户端"+msg);
sendInfoToOtherClients(msg,channel);
}
}catch (Exception e){
try {
System.out.println(channel.getRemoteAddress()+"下线了..");
key.cancel();
channel.close();
}catch (Exception exception){
exception.printStackTrace();
}
}
}
private void sendInfoToOtherClients(String msg,SocketChannel self) throws IOException{
System.out.println("服务器转发消息中...");
//遍历所有注册到selector上的socketchannel,并排除自己
for(SelectionKey key: selector.keys()){
//通过key取出对应的socketchannel
Channel targetchannel=key.channel();
//排除自己
if((targetchannel instanceof SocketChannel)&&(targetchannel!=self)){
SocketChannel dest=(SocketChannel) targetchannel;
ByteBuffer byteBuffer=ByteBuffer.wrap(msg.getBytes());
dest.write(byteBuffer);
}
}
}
public static void main(String[] args) {
ChatServer chatServer = new ChatServer();
chatServer.listen();
}
}
客户端:
package com.songguo.GroupChat;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
public class GroupChatClient {
private final String HOST="127.0.0.1";//服务器的ip
private final int PORT=8080;
private Selector selector;
private SocketChannel channel;
private String username;
//构造器
public GroupChatClient() throws IOException {
selector=Selector.open();
//连接服务器
channel=channel.open(new InetSocketAddress("127.0.0.1",PORT));
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
username = channel.getLocalAddress().toString().substring(1);
System.out.println(username+" is ok...");
}
//向服务器发送消息
public void sendInfo(String msg){
msg=username+"说:"+msg;
try {
channel.write(ByteBuffer.wrap(msg.getBytes()));
}catch (Exception e){
e.printStackTrace();
}
}
//从服务器端回复的消息
public void readmsg(){
try {
int read= selector.select();
if(read>0){
//有可用的通道
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
if(selectionKey.isReadable()){
//如果是可读的就得到相关的通道
SocketChannel channel =(SocketChannel) selectionKey.channel();
ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
channel.read(byteBuffer);
String msg = new String(byteBuffer.array());
System.out.println(msg.trim());
}
iterator.remove();
}
}
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception{
GroupChatClient groupChatClient = new GroupChatClient();
new Thread(){
public void run(){
while(true){
groupChatClient.readmsg();
try {
Thread.currentThread().sleep(3000);
}catch (Exception e){
}
}
}
}.start();
Scanner scanner = new Scanner(System.in);
while(scanner.hasNextLine()){
String s=scanner.nextLine();
groupChatClient.sendInfo(s);
}
}
}
运行截图:
客户端,实现一个读方法,一个写方法,开两个线程,一个一直读,一个一直写
服务端,实现监听方法,如果读到来自某个ip的消息,就转发给所有通道(群聊)