java nio SocketChannel 服务器端与多客户端 信息交互(聊天功能)
来源:互联网 发布:淘宝搜索规则 编辑:程序博客网 时间:2024/05/17 12:48
java nio SocketChannel 服务器端与多客户端 信息交互(聊天功能)
服务器端:
Java代码 :
- 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<String, SocketChannel> clientsMap =new HashMap<String, SocketChannel>();
- 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<SelectionKey> 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<String, SocketChannel> 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 staticvoid main(String[] args) throws IOException {
- NIOSServer server = new NIOSServer(7777);
- server.listen();
- }
- }
客户端,可运行启动多个:
Java代码:
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- 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.util.Date;
- import java.util.Set;
- public class NIOClient {
- /*发送数据缓冲区*/
- private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);
- /*接受数据缓冲区*/
- private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);
- /*服务器端地址*/
- private InetSocketAddress SERVER;
- private static Selector selector;
- private static SocketChannel client;
- private static String receiveText;
- private static String sendText;
- private staticint count=0;
- public NIOClient(int port){
- SERVER = new InetSocketAddress("localhost", port);
- init();
- }
- public void init(){
- try {
- /*
- * 客户端向服务器端发起建立连接请求
- */
- SocketChannel socketChannel = SocketChannel.open();
- socketChannel.configureBlocking(false);
- selector = Selector.open();
- socketChannel.register(selector, SelectionKey.OP_CONNECT);
- socketChannel.connect(SERVER);
- /*
- * 轮询监听客户端上注册事件的发生
- */
- while (true) {
- selector.select();
- Set<SelectionKey> keySet = selector.selectedKeys();
- for(final SelectionKey key : keySet){
- handle(key);
- };
- keySet.clear();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public staticvoid main(String[] args) throws IOException {
- NIOClient client = new NIOClient(7777);
- }
- private void handle(SelectionKey selectionKey)throws IOException{
- if (selectionKey.isConnectable()) {
- /*
- * 连接建立事件,已成功连接至服务器
- */
- client = (SocketChannel) selectionKey.channel();
- if (client.isConnectionPending()) {
- client.finishConnect();
- System.out.println("connect success !");
- sBuffer.clear();
- sBuffer.put((new Date().toLocaleString()+" connected!").getBytes());
- sBuffer.flip();
- client.write(sBuffer);//发送信息至服务器
- /* 原文来自站长网
- * 启动线程一直监听客户端输入,有信心输入则发往服务器端
- * 因为输入流是阻塞的,所以单独线程监听
- */
- new Thread(){
- @Override
- public void run() {
- while(true){
- try {
- sBuffer.clear();
- InputStreamReader input = new InputStreamReader(System.in);
- BufferedReader br = new BufferedReader(input);
- sendText = br.readLine();
- /*
- * 未注册WRITE事件,因为大部分时间channel都是可以写的
- */
- sBuffer.put(sendText.getBytes());
- sBuffer.flip();
- client.write(sBuffer);
- } catch (IOException e) {
- e.printStackTrace();
- break;
- }
- }
- };
- }.start();
- }
- //注册读事件
- client.register(selector, SelectionKey.OP_READ);
- } else if (selectionKey.isReadable()) {
- /*
- * 读事件触发
- * 有从服务器端发送过来的信息,读取输出到屏幕上后,继续注册读事件
- * 监听服务器端发送信息
- */
- client = (SocketChannel) selectionKey.channel();
- rBuffer.clear();
- count=client.read(rBuffer);
- if(count>0){
- receiveText = new String( rBuffer.array(),0,count);
- System.out.println(receiveText);
- client = (SocketChannel) selectionKey.channel();
- client.register(selector, SelectionKey.OP_READ);
- }
- }
- }
- } 原文来自java教程网 http://www.software8.co/wzjs/java/ 欢迎java爱好者前来投稿
- java nio SocketChannel 服务器端与多客户端 信息交互(聊天功能)
- java nio SocketChannel 服务器端与多客户端 信息交互(聊天功能)
- java nio SocketChannel (聊天功能)+NIO介绍
- 用socketchannel实现多客户端与服务器端的通信
- Java NIO 学习(四)--ServerSocketChannel与SocketChannel
- Java NIO(六)--ServerSocketChannel与SocketChannel
- Android手机客户端与服务器端的信息通信交互
- java客户端和服务器端的信息交互(窗口形式,不过窗口很丑)
- Java NIO SocketChannel客户端例子(支持连接失败后自动重连)
- Java NIO系列教程(八) SocketChannel
- Java NIO系列教程(八) SocketChannel
- Java NIO系列教程(五) SocketChannel
- Java NIO系列教程(八) SocketChannel
- Java NIO系列教程(五) SocketChannel
- Java NIO系列教程(八) SocketChannel
- Java NIO系列教程(八) SocketChannel
- Java NIO系列教程(八) SocketChannel
- Java NIO系列教程(八) SocketChannel
- 三层嵌套gridview 的折叠展开
- 2006TECHED广州才一天半,郁闷
- asp.net 2.0下一个标准GRIDVIEW功能的实现(不用datasource控件)
- TOMCAT启动异常
- 如何判断一个点是否在三角形内部
- java nio SocketChannel 服务器端与多客户端 信息交互(聊天功能)
- 开源沙盒分析引擎
- MSDN library 2006 5月提供免费下载了
- Rup架构视图
- java.lang.UnsupportedClassVersionError的错误解决
- PowerDesigner15在win7-64位系统下对MySQL 进行反向工程以及建立物理模型产生SQL语句步骤图文傻瓜式详解
- sql server 2005中对CLR的允许设置
- Eclipse 组织跨平台开发 Cocos2d-x 游戏
- Spring中配合hibernate使用的简单例子