java socket客户端 nio_java nio SocketChannel 服务器端与多客户端 信息交互(聊天功能)...

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;

public class NIOSServer {

private int port = 8888;

//解码buffer

private Charset cs = Charset.forName("gbk");

/*接受数据缓冲区*/

private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);

/*发送数据缓冲区*/

private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);

/*映射客户端channel */

private Map clientsMap = new HashMap();

private static Selector selector;

public NIOSServer(int port){

this.port = port;

try {

init();

} catch (Exception e) {

e.printStackTrace();

}

}

private void init() throws IOException{

/*

*启动服务器端,配置为非阻塞,绑定端口,注册accept事件

*ACCEPT事件:当服务端收到客户端连接请求时,触发该事件

*/

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("server start on port:"+port);

}

/**

* 服务器端轮询监听,select方法会一直阻塞直到有相关事件发生或超时

*/

private void listen(){

while (true) {

try {

selector.select();//返回值为本次触发的事件数

Set 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()) {

/*

* 客户端请求连接事件

* serversocket为该客户端建立socket连接,将此socket注册READ事件,监听客户端输入

* READ事件:当客户端发来数据,并已被服务器控制线程正确读取时,触发该事件

*/

server = (ServerSocketChannel) selectionKey.channel();

client = server.accept();

client.configureBlocking(false);

client.register(selector, SelectionKey.OP_READ);

} else if (selectionKey.isReadable()) {

/*

* READ事件,收到客户端发送数据,读取数据后继续注册监听客户端

*/

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(client.toString()+":"+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 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) throws IOException {

NIOSServer server = new NIOSServer(7777);

server.listen();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值