基于 JAVA NIO 的socket通信
来源:互联网 发布:电视剧全集获取源码 编辑:程序博客网 时间:2024/05/19 14:55
转载自http://blog.csdn.net/z69183787/article/details/52945585
基于NIO创建的客户端,只是发送数据,基于NIO创建的服务端只是接受数据
一个简单入门案例,贴代码:
1.客户端
package cn.itcast.nio;import java.io.IOException;import java.net.InetAddress;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;public class TcpNioClient extends Thread {private InetSocketAddress address;private SocketChannel channel;private String msg;public TcpNioClient(String hostname,int port,String msg){address = new InetSocketAddress(hostname, port);this.msg = msg;System.out.println("------客户端发送数据----"+msg);}@Overridepublic void run() {try {channel = SocketChannel.open();channel.configureBlocking(false);channel.connect(address);if(channel.finishConnect()){//两个buffer,区分用,异步的ByteBuffer buffer = ByteBuffer.allocate(1024);if(buffer.hasRemaining()){channel.write(ByteBuffer.wrap(msg.getBytes()));}//程序会在这里阻塞,因为服务端没有写回数据while(true){buffer.clear();int readnum = channel.read(buffer);if(readnum>0){buffer.flip();System.out.println("客户端 ---receive data:"+new String(buffer.array(), 0, readnum));channel.close();break;}}}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {for(int i=0;i<5;i++){TcpNioClient client = new TcpNioClient("127.0.0.1", 23000, "hello world"+i);client.start();}}}
2. 服务端
package cn.itcast.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.util.Iterator;import javax.rmi.CORBA.Tie;public class NioTcpServer extends Thread {private final InetSocketAddress socketAddress;private Handler handler = new ServerHandler();public NioTcpServer(String localname,int port){socketAddress = new InetSocketAddress(localname, port);}@Overridepublic void run() {try {ServerSocketChannel serverChannel = ServerSocketChannel.open();serverChannel.bind(socketAddress);serverChannel.configureBlocking(false);Selector select = Selector.open();serverChannel.register(select, SelectionKey.OP_ACCEPT);while(true){ //选择信道,开始操作 int num =select.select();if(num>0){Iterator<SelectionKey> iterator = select.selectedKeys().iterator();while(iterator.hasNext()){SelectionKey ky = iterator.next();if(ky.isAcceptable()){handler.handleAccept(ky);}else if(ky.isReadable()){handler.readMsg(ky);}else if(ky.isWritable()){handler.writerMsg(ky);}//将键从键集中移除,新连接会阻塞,无法连接上服务器iterator.remove();}}}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {NioTcpServer tcp = new NioTcpServer("127.0.0.1", 23000);tcp.start();}}
3.服务端,对不同兴趣集操作信道的接口
package cn.itcast.nio;import java.io.IOException;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;public interface Handler {void readMsg(SelectionKey key) throws IOException;void handleAccept(SelectionKey key) throws IOException;void writerMsg(SelectionKey key) throws IOException;}
package cn.itcast.nio;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.SelectableChannel;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import javax.print.attribute.standard.Severity;public class ServerHandler implements Handler {@Overridepublic void handleAccept(SelectionKey key) throws IOException {//接受请求的连接,并获取新的连接,并将新的连接注册到信道上,兴趣集为读ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();SocketChannel acceptChannel = serverChannel.accept();if(acceptChannel!=null){acceptChannel.configureBlocking(false);//再注册前,信道必须设置为非阻塞的acceptChannel.register(key.selector(), SelectionKey.OP_READ);}}@Overridepublic void readMsg(SelectionKey key) throws IOException {SocketChannel channel = (SocketChannel)key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);buffer.clear();int readNum ;if((readNum=channel.read(buffer))>0){buffer.flip();System.out.println("服务端 receive :"+readNum+"bytes");System.out.println("服务端 接受到的数据 data:"+new String(buffer.array(), 0, readNum));buffer.flip();channel.write(buffer);}channel.close();}@Overridepublic void writerMsg(SelectionKey key) throws IOException {//获取附件信息Object obj = key.attachment();SocketChannel sc = (SocketChannel) key.channel();if(obj!=null){ByteBuffer buffer = ByteBuffer.wrap(obj.toString().getBytes());sc.write(buffer);key.interestOps(SelectionKey.OP_READ);buffer.compact();}}}几点需要注意的:
1. 在注册信道前,将信道配置为非阻塞,否则会报异常IllegalBlockingModeException
2. 写数据,读数据时候,注意要操作使用clear,flip方法操作缓冲区的limit,position
3. 由于是异步的,读取数据时候需要判断,返回的int的返回值,写数据时候,要判断缓冲区是否有数据
上述实现,NioTcpServer服务线程启动后,监听指定端口,等待客户端请求的到来,然后NioTcpClient客户端进程启动并发送请求数据,服务端接收到请求数据后,响应客户端(将请求的数据作为响应数据写回到客户端通道SocketChannel,并等待客户端处理)。
实际上,客户端和服务端可以采用同样轮询的非阻塞模式来实现,为简单实现在这个例子中我们把客户端角色简化了,而实际上它可能在另一个系统通信中充当服务端角色。
另外,上面对于不同事件是采用非线程的方式来处理,只是简单地调用处理的方法。在实际中,如果存在大量连接、读写请求,可以考虑使用线程池来更大程度地并发处理,提高服务端处理的速度和吞吐量,提升系统性能。
阅读全文
0 0
- 基于Java NIO的Socket通信
- 基于Java NIO的Socket通信
- 基于Java NIO的Socket通信
- 基于Java NIO 的socket通信实例
- 基于Java NIO的Socket通信
- 基于Java NIO的Socket通信
- 基于Java NIO的Socket通信
- 基于Java NIO的Socket通信
- 基于Java NIO的Socket通信
- 基于 JAVA NIO 的socket通信
- 基于JAVA NIO的socket通信
- Java TCP/IP Socket,基于NIO的TCP通信
- Java NIO Socket通信
- Java NIO Socket通信
- Java NIO Socket通信
- java NIO Socket通信
- Java NIO Socket通信
- 【Java TCP/IP Socket】基于NIO的TCP通信(含代码)
- IS-IS LSP分片扩展
- JavaScript中callee和caller的用法解读
- Ubuntu与Centos的Hadoop安装以及编译运行MapReduce,Hadoop集群安装配置教程
- SpringBoot 中文手册 --Part IV --30 使用NoSQL技术
- 简单代码实现TabLayout 条目的图文混排
- 基于 JAVA NIO 的socket通信
- Mac 常用命令行
- SpannableString两种匹配方法分析(第一种为模仿微博内容匹配)
- sed正则表达式
- VirtualBox Centos安装增强工具并实现文件夹共享
- 获取控件宽高
- 求最小环 floyed 与 dijkstra
- 【工具】福昕阅读器快捷键
- 网站建设解决响应式网站图片响应式难题