服务器端:

import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
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.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;

public class TCPServer {

	protected Selector selector;
	protected Charset charset = Charset.forName("UTF-8");
	protected CharsetEncoder charsetEncoder = charset.newEncoder();
	protected CharsetDecoder charsetDecoder = charset.newDecoder();
	int count = 1;

	/**
	 * @throws Exception
	 */
	public TCPServer() throws Exception{
		this(8888);
	}

	/**
	 * @param port
	 * @throws Exception
	 */
	public TCPServer(int port) throws Exception {
		selector = Selector.open();
		ServerSocketChannel ssc = ServerSocketChannel.open();
		ssc.socket().bind(new InetSocketAddress(port)); // port
		ssc.configureBlocking(false);
		ssc.register(selector, SelectionKey.OP_ACCEPT);// register

		while (true) {
			// selector 线程。select() 会阻塞,直到有客户端连接,或者有消息读入
			selector.select();
			Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
			while (iterator.hasNext()) {
				SelectionKey selectionKey = iterator.next();
				iterator.remove(); // 删除此消息
				// 并在当前线程内处理
				handleSelectionKey(selectionKey);
			}
		}

	}

	/**
	 * @param selectionKey
	 * @throws Exception
	 */
	public void handleSelectionKey(SelectionKey selectionKey) throws Exception {
		if (selectionKey.isAcceptable()) {
			ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
			SocketChannel socketChannel = ssc.accept();
			socketChannel.configureBlocking(false);
			Socket socket = socketChannel.socket();
			// 立即注册一个 OP_READ 的SelectionKey, 接收客户端的消息
			SelectionKey key = socketChannel.register(selector,SelectionKey.OP_READ);

			SocketAddress clientInfo = socket.getRemoteSocketAddress();
			key.attach("第 " + (count++) + " 个客户端 [" + clientInfo + "]");
			// 打印
			println(key.attachment() + " 连接成功");

		} else if (selectionKey.isReadable()) {

			// 有消息进来
			ByteBuffer byteBuffer = ByteBuffer.allocate(100);
			SocketChannel sc = (SocketChannel) selectionKey.channel();

			try {
				int len = sc.read(byteBuffer);
				// 如果len>0,表示有输入。如果len==0, 表示输入结束。需要关闭 socketChannel
				if (len > 0) {
					byteBuffer.flip();
					String msg = charsetDecoder.decode(byteBuffer).toString();
					println(selectionKey.attachment() + " :" + msg);

					// 根据客户端的消息,查找到对应的输出
					String newMsg = "****************";
					ByteBuffer bt = charsetEncoder.encode(CharBuffer.wrap(newMsg + "\n"));
					sc.write(bt);
				} else {
					// 输入结束,关闭 socketChannel
					println(selectionKey.attachment()+ " 已关闭连接");
					sc.close();
				}

			} catch (Exception e) {
				// 如果read抛出异常,表示连接异常中断,需要关闭 socketChannel
				e.printStackTrace();
				sc.close();
			}
		} else if (selectionKey.isWritable()) {
			println("TODO: isWritable()");
		} else if (selectionKey.isConnectable()) {
			println("TODO: isConnectable()");
		} else {
			println("TODO: else");
		}

	}

	/**
	 * @param object
	 */
	public static void println(Object object) {
		System.out.println(object);
	}

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		new TCPServer();
	}

}

客户端:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.io.InputStream;

public class TCPClient extends Thread {

	public void run() {
		try {
			Socket socket = new Socket("127.0.0.1", 8888);
			OutputStream ous = socket.getOutputStream();
			InputStream ins = socket.getInputStream();
			BufferedReader r = new BufferedReader(new InputStreamReader(ins, "UTF-8"));

			// 发送服务器
			ous.write(">>>>>>>>>>>>>>>>".getBytes("UTF-8"));
			ous.flush();
			// 接收给服务器
			System.out.println(">>>> " + r.readLine());

			// 发送服务器
			ous.write("<<<<<<<<<<<<<<<<".getBytes("UTF-8"));
			ous.flush();
			// 接收服务器
			System.out.println(">>>> " + r.readLine());

			Thread.sleep(3*1000);

			ins.close();
			ous.close();
			socket.close();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		for (int i = 0; i < 3; i++) {
			try {
				new TCPClient().start();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}

}

Java异步通信的更多相关文章

  1. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  2. JAVA NIO 类库的异步通信框架netty和mina

    Netty 和 Mina 我究竟该选择哪个? 根据我的经验,无论选择哪个,都是个正确的选择.两者各有千秋,Netty 在内存管理方面更胜一筹,综合性能也更优.但是,API 变更的管理和兼容性做的不是太 ...

  3. JAVA NIO异步通信框架MINA选型和使用的几个细节(概述入门,UDP, 心跳)

    Apache MINA 2 是一个开发高性能和高可伸缩性网络应用程序的网络应用框架.它提供了一个抽象的事件驱动的异步 API,可以使用 TCP/IP.UDP/IP.串口和虚拟机内部的管道等传输方式.A ...

  4. c#与JAVA利用SOCKET实现异步通信的SanNiuSignal.DLL已开源

    大家好,前段时间C#的SanNiuSignal.DLL已开源;因部分用户特需要JAVA版的SanNiuSignal;现在只能把半成品先拿出来暂时给他们用了,以后再慢慢改进; JAVA版目前已实现跟C# ...

  5. Java基础知识强化之网络编程笔记24:Android网络通信之 AndroidAsync(基于nio的异步通信库)

    1. AndroidAsync   AndroidAsync 是一个基于nio的异步socket ,http(客户端服务器端),websocket,socket.io库,AndroidAsync 是一 ...

  6. Java消息队列--JMS概述

    1.什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送 ...

  7. 【历史】JavaScript和Java没啥关系!————JavaScript简史

    文章的开始先上张图: 图片拍摄自北京图书大厦,代表着现在国内应该是绝大部分书店的现状--Javascript书籍放在Java类当中.甚至很多业内人也一直认为Javascript是Java语言在浏览器内 ...

  8. 3.开发Java消息驱动bean实例代码

    java消息服务(JMS)是用于访问企业消息系统的开发商中立的API.企业消息系统可以协助应用软件通过网络进行消息交互.应用程序A发送一条消息到消息服务器的某个目的地(Destination),然后消 ...

  9. JMS(Java消息服务)入门教程

    什么是Java消息服务 Java消息服务指的是两个应用程序之间进行异步通信的API,它为标准消息协议和消息服务提供了一组通用接口,包括创建.发送.读取消息等,用于支持JAVA应用程序开发.在J2EE中 ...

随机推荐

  1. python类库numpy中常见函数的用法

    1. numpy.reshape  重塑 reshape是一种函数,函数可以重新调整矩阵的行数.列数.维数. B = reshape(A,m,n) 返回一个m*n的矩阵B, B中元素是按列从A中得到的 ...

  2. 如何导入python中的模块

    作为一名新手Python程序员,你首先需要学习的内容之一就是如何导入模块或包.但是我注意到,那些许多年来不时使用Python的人并不是都知道Python的导入机制其实非常灵活.在本文中,我们将探讨以下 ...

  3. mongo数据删除和游标

    数据删除 db.集合.remove(删除条件,是否只删除一个数据);默认删多条(false)true删除一条db.集合.remove({}) 删除所有元素但集合还在db.集合.drop() 删除集合 ...

  4. 通过AIDL在两个APP之间Service通信

    一.项目介绍 [知识准备] ①Android Interface definition language(aidl,android接口定义语言),其目的实现跨进程的调用.进程是程序在os中执行的载体, ...

  5. DataOutputStream&DataInputStream

    DataOutputStream&DataInputStream是对输出输入流的扩展,可以直接读写int double等数据类型 下面是今天的练习,细节都写到注释里面了: package Zh ...

  6. python 循环和file操作实现用户密码输错三次将用户锁定

    一.需求编写登录接口1.输入用户名密码2.认证成功后显示欢迎信息3.输错三次后锁定 二.简单思路登录,三次密码输入错误锁定用户1.用户信息文件:存放用户名和密码2.黑名单文件:将输入三次错误的用户加入 ...

  7. 干货!一次kafka卡顿事故排查过程

    由于一次功能上线后,导致某数据量急剧下滑,给我们紧张的呢!排查过程也是个学习过程(这其中有大部分是领导们的功劳,不过分享给大家应该也不犯法吧,ᐓ) 1. 确认问题的真实性? 被数据部门告知,某数据量下 ...

  8. Go 语言切片(Slice)

    Go 语言切片是对数组的抽象. Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固 ...

  9. Docker如何获取镜像

    可以使用 docker pull 命令来从仓库获取所需要的镜像. 下面的例子将从 Docker Hub 仓库下载一个 Ubuntu 12.04 操作系统的镜像. $ sudo docker pull ...

  10. NLP系列(5)_从朴素贝叶斯到N-gram语言模型

    作者: 龙心尘 && 寒小阳 时间:2016年2月. 出处: http://blog.csdn.net/longxinchen_ml/article/details/50646528 ...