服务端代码如下:
import java.io.IOException;
import java.net.InetSocketAddress;
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.Iterator;
import java.util.Set;
/**
* @author sky
* @date 2015-6-27 下午2:56:34
*/
public class MultiTimeServer implements Runnable {
/**
* 服务端选择器
*/
private Selector selector;
/**
* 服务端套接字通道
*/
private ServerSocketChannel serverSocketChannel;
/**
* 消息内容编码
*/
private Charset UTF_8 = Charset.forName("utf-8");
/**
* 是否停止工作标志
*/
private volatile boolean stop;
public static void main(String[] args) {
new Thread(new MultiTimeServer(8889)).start();
}
public MultiTimeServer(String ipAddr, int port) {
if (ipAddr == null || "".equals(ipAddr)) {
ipAddr = "127.0.0.1";
}
try {
selector = Selector.open();
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(new InetSocketAddress(ipAddr,
port));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("开启服务端:MultiTimeServer, 监听端口:" + port );
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public MultiTimeServer(int port) {
this("", port);
}
public void stop() {
this.stop = true;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
while (!stop) {
try {
selector.select(1000); //每次检索等待一秒
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
SelectionKey key = null;
while (it.hasNext()) {
key = it.next();
it.remove();
try {
handleInput(key);
} catch (IOException e) {
if (key != null) {
key.cancel();
if (key.channel() != null) {
key.channel().close();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 处理就绪通道事件
* @author sky
* @date 2015-6-27 下午3:13:46
* @param key
* @throws IOException
*/
private void handleInput(SelectionKey key) throws IOException {
if (key.isValid()) {
if (key.isAcceptable()) { //接收新的请求
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel client = serverSocketChannel.accept();
client.configureBlocking(false); //必须注册为非阻塞模式
client.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) { //通道已经准备好数据进行读取
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(1024); //分配1K
int readByteNum = client.read(readBuffer);
if (readByteNum > 0) { //有输入字节
byte[] bytes = new byte[readByteNum];
readBuffer.flip();
readBuffer.get(bytes);
String body = new String(bytes, UTF_8);
System.out.println(System.currentTimeMillis() + ":" +
body);
client.register(selector, SelectionKey.OP_READ);
doWrite(body, client);
}
}
}
}
/**
* 响应输出
* @author sky
* @date 2015-6-27 下午3:21:48
* @param body
* @throws IOException
*/
private void doWrite(String body, SocketChannel client) throws IOException {
if (body != null && !body.isEmpty()) {
byte[] responseBytes = body.getBytes(UTF_8);
ByteBuffer byteBuffer = ByteBuffer.wrap(responseBytes);
System.out.println(byteBuffer.position() + "," + byteBuffer.limit());
client.write(byteBuffer);
if (!byteBuffer.hasRemaining()) {
System.out.println("sender to client");
}
}
}
}
客户端代码如下:
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.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
/**
* @author sky
* @date 2015-6-27 下午3:26:08
*/
public class MultiTimeClient implements Runnable {
/**
* 选择器
*/
private Selector selector;
/**
* 本地套接字通道
*/
private SocketChannel socketChannel;
/**
* 控制台输入
*/
private BufferedReader reader;
/**
* 消息内容编码
*/
private Charset UTF_8 = Charset.forName("utf-8");
/**
* 服务端端口
*/
private int port;
private String ipAddr;
/**
* 是否停止工作标志
*/
private volatile boolean stop;
public static void main(String[] args) {
new Thread(new MultiTimeClient(8889)).start();
}
public MultiTimeClient(String ipAddr, int port) {
if (ipAddr == null || "".equals(ipAddr)) {
ipAddr = "127.0.0.1";
}
this.port = port;
//创建客户端套接字通道以及连接服务端
try {
selector = Selector.open();
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
reader = new BufferedReader(new InputStreamReader(System.in));
} catch (IOException e) {
e.printStackTrace();
}
}
public MultiTimeClient(int port) {
this("", port);
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
try {
doConnect();
while (!stop) {
selector.select(1000);
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
SelectionKey key = null;
while (it.hasNext()) {
key = it.next();
it.remove();
try {
doInputHand(key);
} catch (Exception e) {
if (key != null) {
key.cancel();
if (key.channel() != null) {
key.channel().close();
}
}
}
}
}
if (selector != null) {
selector.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void doInputHand(SelectionKey key) throws IOException {
if (key.isValid()) {
SocketChannel socketChannel = (SocketChannel) key.channel();
if (key.isConnectable()) { //刚建立连接
if (socketChannel.finishConnect()) { //需要注册可读事件
socketChannel.register(selector, SelectionKey.OP_READ);
doWrite(socketChannel, "hello server!");
} else {
System.exit(1);
}
} else if (key.isReadable()) {
ByteBuffer readBuffer = ByteBuffer.allocate(1024); //分配1K
int readByteNum = socketChannel.read(readBuffer);
if (readByteNum > 0) { //有输入字节
byte[] bytes = new byte[readByteNum];
readBuffer.flip();
readBuffer.get(bytes);
String body = new String(bytes, UTF_8);
System.out.println("Now is:" +
body);
System.out.println("请输入发送:");
String msg = reader.readLine();
doWrite(socketChannel, msg);
socketChannel.register(selector, SelectionKey.OP_READ);
} else {
key.cancel();
socketChannel.close();
}
} else if (key.isWritable()) {
System.out.println("isWritable");
}
}
}
private void doConnect() throws IOException {
if (socketChannel.connect(new InetSocketAddress(ipAddr, port))) {
socketChannel.register(selector, SelectionKey.OP_READ);
doWrite(socketChannel, "hello server!");
} else {
socketChannel.register(selector, SelectionKey.OP_CONNECT);
}
}
private void doWrite(SocketChannel sc, String body) throws IOException {
byte[] req = body.getBytes(UTF_8);
ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);
writeBuffer.put(req);
writeBuffer.flip();
sc.write(writeBuffer);
if (!writeBuffer.hasRemaining()) {
System.out.println("send to server success!");
}
}
}
分享到:
相关推荐
Java NIO非阻塞服务端与客户端相互通信 每行代码都有注释, 看完后,会让你对非阻塞有一清楚的认识.
利用idea,构建的maven项目,用idea打开即可测试运行,实现了netty的服务段和客户端,利用netty实现服务端和客户端的通信demo.
Java开发基于多线程和NIO实现聊天室源码+项目说明(含服务端+客户端).zip 涉及到的技术点 - 线程池ThreadPoolExecutor - 阻塞队列BlockingQueue,生产者消费者模式 - Selector - Channel - ByteBuffer - ...
java NIO 创建的服务端,能够异步响应客户端的请求,客户端采用nio异步请求服务端,通信之间的乱码使用charset解决
网络通信工具,服务端和客户端连接测试工具,可单条发送,循环发送,模拟多客户端发送,本工具可以作为网络通信工具或压力测试工具, Java NIO Socket编程,需JAVA运行环境
CS模式聊天程序代码,实现语言为Java,前端UI界面用Java Swing框架实现,服务端与客户端通信采用Java NIO,自定义按分隔符\n读取消息的消息读取格式解决TCP粘包拆包问题。
nettyproject NIO编程 基于netty通信框架的服务端,客户端编程 源码阅读。 netty服务端。 网友客户端1118
Java网络编程是指使用Java编程语言进行网络通信和相关操作的技术。...Socket服务端和客户端:开发基于Socket的服务端和客户端程序,实现双向通信和数据交换。 NIO(New I/O):Java NIO提供了非阻
1、支持TCP/IP协议的网络通信,TCP服务端和客户端,可单条发送,循环发送,模拟多客户端发送; 2、支持HTTP协议的网络通信, HTTP协议的服务端和客户端连接测试工具; 3、网络扫描工具,可扫描主机端口及扫描局域网内的...
本源码是《NIO框架入门(二):服务端基于MINA2的UDP双向通信Demo演示》一文的Java客户端源码实现,详见:http://www.52im.net/thread-373-1-1.html
Voovan 是一个高性能异步网络框架和WEB服务器框架,同时支持HTTP客户端抓取、动态编译支持、数据库访问封装以及DateTime、String、Log、反射、对象工具、流操作、文件操作、异步双向通道等功能。旨在提供可靠、方便、...
最近在看Netty相关的资料,刚好SOFA-BOLT是一个比较成熟的Netty自定义协议栈实现,于是决定研读SOFA-BOLT的源码,详细分析其协议的组成,简单分析其客户端和服务端的源码实现。 吐槽一下:SOFA-BOLT的代码缩进和...
这是一个基于高并发网络框架-Netty框架的demo项目,旨在展示Netty服务端与客户端的基础使用方式,并深入探讨了自定义编解码器以及心跳机制的实现。本demo紧密结合了本人发布的《初识Netty》一文中的示例,为学习者...
1.客户端连接服务端,服务端通过Selector接收到连接请求,将其socketChannel通道保存到通道集合,并触发客户端连接事件 2.客户端发送数据包请求到服务端,服务端将请求的SelectionKey压入“读消息生产者队列”,立即...
NIO服务端10 2.2. NIO客户端13 3.Netty源码分析16 3.1. 服务端创建16 3.1.1. 服务端启动辅助类ServerBootstrap16 3.1.2. NioServerSocketChannel 的注册21 3.1.3. 新的客户端接入25 3.2. 客户端创建28 3.2.1. ...
HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件、客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++、C#、Delphi、E(易语言)、Java、Python 等编程语言接口...
java NIO服务端和客户端代码实现 没有说明NIO背后的原理是React器模式. 另外java_mzd的评论值得注意: 文章不错,理解不够! 小路可以先去看看5种IO模式的异同,体会体会,然后可以了解一下EPoll模型。 最后,还可以...
BIO是同步阻塞模型,特点是一对一的客户端与处理线程关系,适用场景是连接数量较小并且固定的,优点是编程简单,但对服务器资源要求高。NIO是同步非阻塞模型,它借助selector能以一对多的方式处理连接,优点是连接...
群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2)实现多人群聊 3)服务器端:可以监测用户上线,离线,并实现消息转发功能 4)客户端:通过channel 可以无阻塞发送消息给其它所有用户,同时可以接受...
Apache的Mina(Multipurpose Infrastructure Networked Applications)是一个... 客户端/服务端框架(典型的C/S架构) 网络套接字(networking socket)类库 事件驱动的异步API(注意:在JDK7中也新增了异步API)