`
tmdpzc
  • 浏览: 13785 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

java NIO 学习 聊天室程序 (1)

阅读更多
学习 java nio ,自己建立一个 nio的聊天室程序。
服务器采用单一线程 轮训,accept的所有端口。

首先定义一个接口,处理 SelectionKey 上的事件。

static interface NioHandler {
		/**
		 * 处理{@link SelectionKey#OP_ACCEPT}事件
		 * 
		 * @param key
		 * @throws IOException
		 */
		void handleAccept(SelectionKey key) throws IOException;

		/**
		 * 处理{@link SelectionKey#OP_READ}事件
		 * 
		 * @param key
		 * @throws IOException
		 */
		void handleRead(SelectionKey key) throws IOException;

		/**
		 * 处理{@link SelectionKey#OP_WRITE}事件
		 * 
		 * @param key
		 * @throws IOException
		 */
		void handleWrite(SelectionKey key) throws IOException;
		/**
		 * 处理IO 异常事件
		 * @param key 
		 * @throws IOException
		 */
		void handleIoError(SelectionKey key) throws IOException;
	}

服务器的run方法中处理io事件


	@Override
	public void run() {
		InetSocketAddress address = new InetSocketAddress(mConfig.port);
		try {
			mSSC  = ServerSocketChannel.open();
			Selector selector = Selector.open();
			mSSC.socket().bind(address);
			mSSC.configureBlocking(false);
			mSSCKey = mSSC.register(selector, SelectionKey.OP_ACCEPT);
			while (true) {
				int events = selector.select();
				if (events == 0) {
					continue; //忽略
				}
				Iterator<SelectionKey> it = selector.selectedKeys().iterator();
				while(it.hasNext()) {
					SelectionKey key = it.next();
					it.remove();
					if (key.isAcceptable()) {
						mIoHandler.handleAccept(key);
					} else if (key.isReadable()) {
						mIoHandler.handleRead(key);
					} else if (key.isWritable()) {
						mIoHandler.handleWrite(key);
					}else {
						break;
					}
				}
				Thread.yield();// 让出执行空间
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new ChatServerException(e);
		}

	}


IoHandler的实现类: ChatIoHandler
class ChatIoHandler implements NioHandler {
		StringBuffer sb = new StringBuffer();

		@Override
		public void handleAccept(SelectionKey key) throws IOException {
			ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
			SocketChannel client = ssc.accept();
			if (client != null) {
				client.configureBlocking(false);
				System.out.println("Accept:"
						+ client.socket().getRemoteSocketAddress().toString());
				client.register(key.selector(), SelectionKey.OP_READ);
				String address = client.socket().getRemoteSocketAddress()
						.toString();
				ChatServer.this.mChannelMap.put(address, client); // 加入map中
			}
			
		}

		@Override
		public void handleRead(SelectionKey key) throws IOException {
			SocketChannel sc = (SocketChannel) key.channel();
			System.out.println("Read from"
					+ sc.socket().getRemoteSocketAddress() + " ");
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			buffer.clear();
			int len = 0;
			StringBuffer sBuffer = new StringBuffer();
			while ((len = sc.read(buffer)) > 0) {
				buffer.flip();
				sBuffer.append(new String(buffer.array(), 0, len));
			}
			//handle socket error;
			if (len < 0) {
				handleIoError(key);
			}
			String msg = sBuffer.toString();
			if (sBuffer.length() > 0) {
				System.out.println("Server receive:" + sBuffer.toString());
			}
			//command 设计模式
			String[] args = msg.split(" ");
			Command cmd = CommandFactory.getInstance().createCommand(args[0]);
			cmd.handleCmd(key, ChatServer.this,args);
		}

		@Override
		public void handleWrite(SelectionKey key) throws IOException {
			// TODO Auto-generated method stub
			SocketChannel  sc = (SocketChannel) key.channel();
			String address = sc.socket().getRemoteSocketAddress().toString();
			System.out.println("handleWrite: " + address);
			String msg = (String) key.attachment();
			if (msg != null) {
				int len = sc.write(ByteBuffer.wrap(msg.getBytes()));
				if (len < 0) {
					//handle error;
					handleIoError(key);
				}
				key.attach(null);
				key.interestOps(SelectionKey.OP_READ);
			}
		}

accept 一个 channel 后,向channel注册server端的 selector ,将感兴趣的事件设为OP_READ
并 将该channel 以socket address  为key 保存在Server端的一个map中。

handleRead中 使用 command 设计模式,将client端穿来的参数 args 解析为命令,调用具体的命令处理方法。

command 抽象类:

package com.tcl.chat.command;

import java.io.IOException;
import java.nio.channels.SelectionKey;

import com.tcl.chat.ChatServer;

public abstract class Command {
	public abstract void handleCmd(SelectionKey key , ChatServer server,String[] args) throws IOException;
}



分享到:
评论

相关推荐

    java NIO 学习 聊天室程序 (3)

    在这个“Java NIO 学习 聊天室程序”项目中,我们将深入探讨NIO如何用于创建一个聊天室程序。这个程序可能包含以下几个关键部分: 1. **服务器端**:服务器端使用NIO的ServerSocketChannel监听客户端连接。当新的...

    JAVA NIO 聊天室程序

    **JAVA NIO 聊天室程序** 在Java编程领域,网络编程是一个重要的部分,而NIO(Non-blocking Input/Output)是Java提供的一种高效、非阻塞的I/O模型,它极大地提升了处理大量并发连接的能力。这个"JAVA NIO 聊天室...

    java NIO socket聊天室

    1,运行server.bat启动服务器,可以打开编辑,修改端口号 2,运行client.bat启动客户端,可以打开编辑,ip,和端口号 3,自己发送的信息,自己是看不到的,运行多个客户端,其他的客户端可以看得到的 4,修改封装...

    非GUI聊天室基于javaNIO

    服务端程序基于javaNIO,客户端程序基于旧IO,读完&lt;&lt;javaNIO&gt;&gt;后,导入eclipse即可运行,支持多人在线聊天,上下线通知.PS:非GUI程序,毕竟javaSwing用的少,不懂的地方大家可以一起讨论,评论必回!

    基于NIO的Java聊天室2

    在本项目"基于NIO的Java聊天室2"中,我们深入探讨了如何利用Java的非阻塞I/O(New Input/Output,NIO)框架来实现一个多人在线聊天室。NIO是一种高效的I/O模型,它允许程序在不阻塞主线程的情况下处理输入和输出操作...

    基于NIO的聊天室

    在这个基于NIO的聊天室项目中,我们可以通过分析`Server.java`、`Client.java`和`NioUtil.java`这三个文件来理解NIO的核心概念和实现方式。 首先,`Server.java`文件通常包含了服务器端的主逻辑。在NIO中,服务器会...

    java多线程程序设计:Java NIO+多线程实现聊天室

    java多线程程序设计:Java NIO+多线程实现聊天室 Java基于多线程和NIO实现聊天室 涉及到的技术点 线程池ThreadPoolExecutor 阻塞队列BlockingQueue,生产者消费者模式 Selector Channel ByteBuffer ProtoStuff 高...

    java基于NIO选择器Selector的多人聊天室

    在这个"java基于NIO选择器Selector的多人聊天室"项目中,开发者利用NIO的核心特性构建了一个允许多个客户端同时进行交互的聊天平台。 首先,我们需要了解NIO的基本组件。在Java NIO中,`Selector`是核心角色,它...

    java聊天室(绝对经典)

    在"JAVA聊天室程序.rar"中,你可能会看到一个基于Swing或JavaFX的图形用户界面(GUI)的实现,这使得用户可以直接在窗口中输入和查看消息。而在"java+Sockt聊天室.rar"中,可能侧重于网络通信的细节,展示了如何通过...

    JAVA综合实验2聊天室

    在本实验中,我们将深入探讨Java编程语言在创建一个简单的聊天室应用中的应用。这个"JAVA综合实验2聊天室"项目旨在让学生理解网络编程的基本原理,特别是如何利用Java实现客户端和服务器之间的通信,以及如何设计多...

    java聊天室程序代码

    Java聊天室程序代码是基于Java编程语言实现的一个多人实时交流平台。这个聊天室的核心功能包括用户注册、登录、发送和接收消息。通过分析提供的压缩包文件名称,我们可以推测出其可能采用了一些并发处理和队列操作的...

    JAVA 开发Java聊天室程序(java)130226

    在本项目"JAVA 开发Java聊天室程序(java)130226"中,我们将深入探讨如何使用Java语言开发一个实时的、多用户交互的聊天室应用。这个项目涉及了多个关键的Java编程概念和技术,包括网络编程、多线程、并发控制以及...

    基于Socket的Java聊天室程序

    Java聊天室程序是一种基于Socket通信技术的多用户交互平台,它允许多个...通过学习和实践这个Java聊天室程序,开发者可以深入理解网络编程、多线程编程以及GUI开发等关键技能,对于提升Java应用开发能力具有重要意义。

    Java即时通讯聊天室

    综上所述,"Java即时通讯聊天室"项目涵盖了网络编程、多线程、安全存储、用户交互等多个核心知识点,是学习和实践Java技术的一个良好平台。通过对这些功能的实现,开发者能够深入理解TCP/IP通信、数据加密、并发控制...

    多线程精品资源--Java NIO+多线程实现聊天室.zip

    在这个“多线程精品资源--Java NIO+多线程实现聊天室”的压缩包中,我们可以推测它包含了一套关于如何使用Java NIO和多线程技术来创建一个实时聊天应用的教程或示例代码。 首先,多线程是Java中并行处理的基础。...

    JavaNIO教程高清

    Java NIO(New I/O)是Java提供的一套新的输入/输出API,自Java 1.4版本起作为标准...Java NIO为处理高性能网络和文件I/O提供了一个强大的工具集,对于需要优化I/O性能的应用程序来说,Java NIO是一个不可或缺的选择。

    JavaNIO浅析IO模型Java开发Java经验技巧共1

    1. **服务器端的高并发场景**:例如聊天室、游戏服务器等,NIO能有效利用资源,处理大量并发连接。 2. **大文件传输**:NIO的缓冲区机制使得大文件传输更加高效。 3. **网络通信**:NIO的非阻塞特性适合处理网络请求...

    Java聊天室程序(java).zip

    1. **Java基础**: 聊天室程序首先需要基于Java的基础语法,包括类、对象、变量、数据类型、控制结构(如if语句和循环)、异常处理等。开发者需要对Java语言有扎实的理解。 2. **多线程**: 为了实现用户间的并发交流...

    Java+Swing聊天室

    5. **网络编程**:聊天室需要通过网络连接进行通信,因此可能使用了Java的Socket编程或者更高层次的API如Java NIO(非阻塞I/O)或Java.net包中的其他类。客户端和服务器之间通过TCP/IP协议交换数据。 6. **数据结构...

Global site tag (gtag.js) - Google Analytics