zoukankan      html  css  js  c++  java
  • java NIO socket 通信实例

    版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/zhuyijian135757/article/details/37672151

    java Nio 通信与Bio通信主要不同点:

    1.Nio中的单个channel就可以支持读操作也能够支持写操作,而bio中读操作要用inputstream,写操作要outputstream.

    2.nio 採用byteBuffer 作为内存缓存区,向channel里写或者度操作,bio基本是用byte[]

    3.nio採用 selector组件轮询读取就绪channel


    服务端demo代码:

    package com.my.socket3;
    import java.io.ByteArrayOutputStream;
    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.util.Iterator;
    import java.util.Set;
    
    import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
    
    public class ServerTest {
    
    	public static void main(String[] args) throws Exception {
    		server();
    	}
    	
    	public static void server(){
    		ServerSocketChannel channel=null;
    		try{
    			
    			Selector selector=Selector.open();
    			channel=ServerSocketChannel.open();
    			channel.configureBlocking(false);
    			channel.socket().setReuseAddress(true); 
    			channel.bind(new InetSocketAddress(8020));
    			channel.register(selector, SelectionKey.OP_ACCEPT,new Integer(1));
    				
    			while(true){
    				if(selector.select()>0){
    					Set<SelectionKey> sets=selector.selectedKeys();
    					Iterator<SelectionKey> keys=sets.iterator();
    					while(keys.hasNext()){
    						SelectionKey key=keys.next();
    						keys.remove();
    						
    						if(key.isAcceptable()){
    							key.attach(new Integer(1));
    							SocketChannel schannel=((ServerSocketChannel) key.channel()).accept();
    							schannel.configureBlocking(false);
    							schannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
    						}
    						
    						if(key.isReadable()){
    							SocketChannel schannel=(SocketChannel) key.channel();
    							ByteBuffer buf=ByteBuffer.allocate(1024);
    							ByteOutputStream output=new ByteOutputStream();
    							int len=0;
    							while((len=schannel.read(buf))!=0){
    								buf.flip();
    								byte by[]=new byte[buf.remaining()];
    								buf.get(by);
    								output.write(by);
    								buf.clear();
    							}
    							String str=new String(output.getBytes());
    							key.attach(str);
    						}
    						
    						if(key.isWritable()){
    							
    							Object object=key.attachment();
    							String attach=object!=null ? "server replay: "+object.toString() : "server replay: ";
    							SocketChannel schannel=(SocketChannel) key.channel();
    							schannel.write(ByteBuffer.wrap(attach.getBytes()));  
    						}
    					}
    				}
    			}
    		}catch(Exception e){
    			e.printStackTrace();
    		}finally{
    			if(channel!=null){
    				try {
    					channel.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		
    	}
    }
    

    客户端demo代码

    package com.my.socket3;
    import java.io.ByteArrayOutputStream;
    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.SocketChannel;
    import java.util.Iterator;
    import java.util.Set;
    
    public class ClientTest {
    
    	public static void main(String[] args) throws Exception {
    				client();
    	}
    	
    	public static void client() {
    		SocketChannel channel=null;
    		try {
    			
    			Selector selector=Selector.open();
    			channel = SocketChannel.open();
    			channel.configureBlocking(false);
    			channel.connect(new InetSocketAddress(8020));
    			channel.register(selector, SelectionKey.OP_CONNECT);
    			
    			while(true){
    				if(selector.select()>0){
    					
    					Iterator<SelectionKey> set=selector.selectedKeys().iterator();
    					while(set.hasNext()){
    						SelectionKey key=set.next();
    						set.remove();
    						
    						SocketChannel ch=(SocketChannel) key.channel();
    						if(key.isConnectable()){
    							ch.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE,new Integer(1));
    							ch.finishConnect();
    						}
    						
    						if(key.isReadable()){
    							key.attach(new Integer(1));
    							ByteArrayOutputStream output=new ByteArrayOutputStream();
    							ByteBuffer buffer=ByteBuffer.allocate(1024);
    							int len=0;
    							while((len=ch.read(buffer))!=0){
    								buffer.flip();
    								byte by[]=new byte[buffer.remaining()];
    								buffer.get(by);
    								output.write(by);
    								buffer.clear();
    							}
    							System.out.println(new String(output.toByteArray()));
    							output.close();
    						}
    						
    						if(key.isWritable()){
    							key.attach(new Integer(1));
    							ch.write(ByteBuffer.wrap((("client say:hi")).getBytes()));
    						}
    					}
    				}
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally{
    			try {
    				channel.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	
    	static class ClientRunnable implements Runnable{
    
    		private SocketChannel ch;
    		
    		private ClientRunnable(SocketChannel ch){
    			this.ch=ch;
    		}
    		
    		@Override
    		public void run() {
    			try {
    				while(true){
    					ch.write(ByteBuffer.wrap((("client say:hi")).getBytes()));
    					Thread.sleep(5000);
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    				try {
    					ch.close();
    				} catch (IOException e1) {
    					e1.printStackTrace();
    				}
    			}
    		}
    	}
    	
    
    }
    

    跑demo时遇到的问题

    1.客户端须要进行 ch.finishiCnonnect()操作,否则两边都堵塞着

    2.读channel中的bytebuffer时, while((len=ch.read(buffer))!=0) 推断不要写成while((len=ch.read(buffer))!=-1) 

    假设SocketChannel被设置为非堵塞,则它的read操作可能返回三个值:
    1) 大于0,表示读取到了字节数。
    2) 等于0。没有读取到消息,可能TCP处于Keep-Alive状态,接收到的是TCP握手消息。
    3) -1,连接已经被对方合法关闭。


查看全文
  • 相关阅读:
    Excel导入导出DataGridView
    博客开通第一天
    windows10 VM12 安装Mac OS X 10.11
    js判断IE浏览器及版本
    C# MD5 加密
    WindowsErrorCode
    localStorage,sessionStorage的使用
    js实现页面锚点定位动画滚动
    纯js实现页面返回顶部的动画
    HTML table固定表头
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10919724.html
  • Copyright © 2011-2022 走看看