java nio代码_Java网络编程-Nio 实例代码

本文展示了如何使用Java NIO(非阻塞I/O)实现一个服务器和客户端的通信示例。服务器端创建了一个非阻塞的ServerSocketChannel,监听8787端口,接收客户端连接并读写数据。客户端通过SocketChannel连接服务器,发送和接收消息。整个过程利用Selector进行事件选择和处理,提高了系统效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基于Nio的 Server ,过程略复杂,但是无疑这样的效率高;代码中得注释比较详细,请看注释说明

package com.zhuoxuan.net.nio;

import java.io.IOException;

import java.net.InetSocketAddress;

import java.net.ServerSocket;

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.util.Iterator;

import java.util.Random;

import java.util.Set;

/**

*

*

* 基于nio的Server

*

*

* @author 卓轩

* @创建时间:2014年7月7日

* @version: V1.0

*/

public class NioServer {

private final int port = 8787;

private final int BLOCK_SIZE = 4096;

private Selector selector;

private ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK_SIZE);

private ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK_SIZE);

//构造函数

public NioServer() throws IOException {

//打开服务器套接字通道

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

//服务器配置为非阻塞模式

serverSocketChannel.configureBlocking(false);

//获取与通道关联的 ServerSocket对象

ServerSocket serverSocket = serverSocketChannel.socket();

//绑定端口

serverSocket.bind(new InetSocketAddress(port));

//打开一个选择器

selector = Selector.open();

//注册到selector上,等待连接

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

System.out.println("Server:init successfuly.");

}

/**

* 监听端口

*/

private void linstenr() throws Exception{

while (true) {

//选择一组键

selector.select();

//返回获取选择的键集

Set selectionKeys = selector.selectedKeys();

if(selectionKeys.isEmpty()){

continue;

}

//遍历,循环处理请求的键集

Iterator iterator = selectionKeys.iterator();

while (iterator.hasNext()) {

SelectionKey selectionKey = (SelectionKey) iterator.next();

iterator.remove();

handlerKey(selectionKey);

}

Thread.sleep(4000);

}

}

/**

* 处理对应的 SelectionKey

* @param selectionKey

*/

private void handlerKey(SelectionKey selectionKey) throws IOException{

ServerSocketChannel server;

SocketChannel client;

// 测试此键的通道是否已准备好接受新的套接字连接

if(selectionKey.isAcceptable()){

//此键对应的关联通道

server = (ServerSocketChannel)selectionKey.channel();

//接受到此通道套接字的连接

client = server.accept();

//配置为非阻塞

client.configureBlocking(false);

//注册到selector 等待连接

client.register(selector, SelectionKey.OP_READ);

}

else if (selectionKey.isReadable()) {

client = (SocketChannel)selectionKey.channel();

//将缓冲区清空,下面读取

receiveBuffer.clear();

//将客户端发送来的数据读取到 buffer中

int count = client.read(receiveBuffer);

if(count >0){

String receiveMessage = new String(receiveBuffer.array(),0,count);

System.out.println("Server:接受客户端的数据:" + receiveMessage);

client.register(selector, SelectionKey.OP_WRITE);

}

}

else if (selectionKey.isWritable()) {

//发送消息buffer 清空

sendBuffer.clear();

//返回该键对应的通道

client = (SocketChannel)selectionKey.channel();

String sendMessage = "Send form Server...Hello... "+new Random().nextInt(100)+" .";

//向缓冲区中写入数据

sendBuffer.put(sendMessage.getBytes());

//put了数据,标志位被改变

sendBuffer.flip();

//数据输出到通道

client.write(sendBuffer);

System.out.println("Server:服务器向客户端发送数据:" + sendMessage);

client.register(selector, SelectionKey.OP_READ);

}

}

public static void main(String[] args) {

try {

NioServer nioServer = new NioServer();

nioServer.linstenr();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

二、Nio Client 实例

package com.zhuoxuan.net.nio;

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.Iterator;

import java.util.Set;

/**

*

*

* nio client

*

*

* @author 卓轩

* @创建时间:2014年7月7日

* @version: V1.0

*/

public class NioClient {

private static final int BLOCK_SIZE = 4096;

private static ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK_SIZE);

private static ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK_SIZE);

private static final InetSocketAddress SERVER_ADDRESS = new InetSocketAddress("127.0.0.1",8787);

public static void main(String[] args) {

try {

//打开socket通道

SocketChannel socketChannel = SocketChannel.open();

//设置为非阻塞模式

socketChannel.configureBlocking(false);

//打开选择器

Selector selector = Selector.open();

//向selector 选择器注册此通道

socketChannel.register(selector, SelectionKey.OP_CONNECT);

//链接

socketChannel.connect(SERVER_ADDRESS);

SocketChannel client;

while (true) {

//选择一组键

selector.select();

//返回此选择器的已选择键集

Set selectionKeys = selector.selectedKeys();

Iterator iterator = selectionKeys.iterator();

//遍历对应的 SelectionKey 处理

while (iterator.hasNext()) {

SelectionKey selectionKey = (SelectionKey) iterator.next();

//判断此键的通道是否已完成其套接字连接操作

if (selectionKey.isConnectable()) {

System.out.println("Client: already connected.");

client = (SocketChannel)selectionKey.channel();

//判断该通道是否进行连接过程、完成连接过程

if(client.isConnectionPending()){

client.finishConnect();

sendBuffer.clear();

sendBuffer.put("hello nio server".getBytes());

sendBuffer.flip();

client.write(sendBuffer); //将数据写入该通道

client.register(selector, SelectionKey.OP_READ);

}

}

else if(selectionKey.isReadable()){

//获取该键中对应的通道

client = (SocketChannel)selectionKey.channel();

receiveBuffer.clear();

int count = client.read(receiveBuffer);

if(count > 0){

String receiveMessage = new String(receiveBuffer.array(),0,count);

System.out.println("Client:接收到来自Server的消息," + receiveMessage);

client.register(selector, SelectionKey.OP_WRITE);

}

}

else if(selectionKey.isWritable()){

sendBuffer.clear();

client = (SocketChannel) selectionKey.channel();

String sendText = "hello server,key..";

sendBuffer.put(sendText.getBytes());

//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位

sendBuffer.flip();

client.write(sendBuffer);

System.out.println("Client:客户端向服务器端发送数据--:"+sendText);

client.register(selector, SelectionKey.OP_READ);

}

}

selectionKeys.clear();

Thread.sleep(3000);

}

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值