服务端代码如下:
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非阻塞服务端与客户端通信的关键在于利用非阻塞IO和选择器,实现高效的多路复用,有效利用系统资源,提升并发处理能力。通过实践本教程中的代码示例,你将能够清晰地理解这一概念并掌握其应用技巧。
在本文中,我们将深入探讨如何使用 Netty 实现服务端与客户端之间的通信,以及涉及到的关键知识点。 首先,我们要理解 Netty 的核心概念。Netty 基于非阻塞 I/O 模型,利用 Java NIO(Non-blocking Input/Output)...
在"java应用netty服务端和客户端"的示例中,Netty被用来构建一个简单的通信系统,其中包含服务端(Server)和客户端(Client)。为了实现通信,服务端和客户端都需要定义自己的`model对象`,这些对象通常包含了数据...
2. **Android客户端通信**:Android设备作为客户端,需要连接到服务端进行数据交换。Android SDK提供了HttpClient和OkHttp等库用于网络通信,但为了实现高效、低延迟的连接,Netty可以作为一个更好的选择,尤其是当...
以上是对"nio异步长连接服务端与客户端"这一主题的详细讲解,涵盖了NIO的基础概念、异步通信机制以及服务端和客户端的实现细节。通过理解和应用这些知识点,开发者能够构建出高效、稳定的长连接网络应用。
在标题中提到的"JAVA nio异步长连接服务端与客户端",我们可以理解为使用Java NIO实现的TCP长连接通信。TCP长连接是指在客户端和服务端之间保持一个持久的连接,可以多次收发数据,而不必每次通信都建立新的连接。这...
总的来说,这个NIO服务端和客户端的例子可以帮助我们深入理解Java NIO和Netty框架的工作原理,学习如何构建高效、可靠的网络应用。通过实践和分析这个示例代码,我们可以更好地掌握异步I/O、事件驱动编程以及Netty...
在Java编程环境中,服务端和客户端之间的文件传输是常见的需求,尤其在分布式系统或网络应用中。本示例主要涉及的是使用Java的Socket编程来实现这一功能。Socket编程是网络编程的基础,它允许两个网络应用程序之间...
本项目主要探讨了如何使用Java编程语言实现多客户端与服务端之间的通信,具备上线提示、群聊以及私聊功能,这对于构建实时聊天应用或者协同工作平台至关重要。 首先,我们要理解客户端-服务器(Client-Server)架构...
在本文中,我们将深入探讨如何使用 Netty 实现简单的客户端-服务端通信,这对于初学者来说是一个很好的起点。 首先,理解 Netty 的核心概念至关重要。Netty 的设计基于 NIO(非阻塞 I/O),它利用了 Java 提供的 ...
本项目名为"简易服务端&客户端",旨在为开发者提供一个快速、便捷的测试环境,以便于进行网络通信功能的验证和调试。下面我们将深入探讨这个项目所涉及的主要知识点。 首先,服务端是网络应用的核心部分,它负责...
最后,为了实现Socket通信,我们需要定义消息的协议格式,例如JSON、protobuf等,并在服务端和客户端之间交换这些格式化数据。确保两边的消息解析和序列化保持一致。 总结起来,Spring Boot与Netty的整合提供了构建...
在"MINA 服务端和客户端demo"中,我们有两个主要的部分:服务端(Server)和客户端(Client)。这两个部分都是基于MINA框架构建的,分别实现了服务器接收客户端连接、处理数据和客户端发起连接、发送数据的功能。 1...
MINA框架中的Socket服务端和客户端通过Socket接口实现数据的发送和接收,服务端创建监听Socket,等待客户端的连接请求;客户端则通过Socket连接到服务端,进行数据交互。 3. **服务端实现**:在MINA中,服务端通常...
Socket服务端和客户端文件批量传输源码是一种基于TCP/IP协议的网络编程技术,它允许两台计算机通过网络进行数据交换,实现文件的批量传输。在Java等编程语言中,Socket通常被用来创建自定义的通信协议,是进行网络...
异步TCP聊天程序是一种基于网络通信的技术,它允许服务端和客户端通过TCP协议进行实时、高效的数据交换。...在设计和实现这样的系统时,需要考虑网络编程的复杂性,包括连接管理、数据传输的可靠性以及并发处理能力。
- **网络协议**:服务端通常基于TCP或UDP协议,可能使用WebSocket实现双向通信,确保实时性。 - **服务器架构**:可能是基于异步事件驱动的模型(如Node.js的Event Loop)或多线程/多进程模型(如Python的Gevent或...
在这个“用Netty5写一个简单的服务端和客户端”的示例中,我们将探讨如何使用Netty 5版本来构建基本的TCP通信模型,包括单连接和多连接的实现。 首先,Netty 5的核心组件包括Bootstrap(引导类)、Channel(通道)...
- **观察者模式**:服务端可能需要监听客户端的连接和断开事件,这时观察者模式可以帮助实现消息通知。 7. **异常处理**: - 在网络编程中,错误处理非常重要,例如网络中断、超时等异常,都需要进行捕获和处理。...
在这个“netty5服务端和客户端通讯的demo”中,我们将深入探讨如何利用Netty 5实现Java中的服务器和客户端通信。Netty 5(尽管现在Netty已经更新到更高级别的版本)提供了丰富的功能,包括NIO(非阻塞I/O)支持,...