1. 程式人生 > >Java NIO(非同步IO)Socket通訊例子

Java NIO(非同步IO)Socket通訊例子

簡要說明下:使用java nio開發網路通訊 是比較快速和方面的。因為他可以不用阻塞的方式偵聽客戶端的連線 ,在java nio中可以使用基於事件的機制進行非阻塞通訊,當有新的事

件進行註冊時 我們只需要通過事件偵聽機制 獲取新的事件

簡單的說就是 java nio中裡面有一個selector  非同步 I/O 中的核心物件名為 Selector。Selector 就是您註冊對各種 I/O 事件的興趣的地方,而且當那些事件發生時,就是這個物件告訴

您所發生的事件。

我們先給出一個例子把:

package org.web.niotest;
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.Set;

/**
 * java NIO 伺服器端例子
 * @author user
 *
 */
public class Server {
    //伺服器端通道
    ServerSocketChannel ssc;
    public void start(){
        try {
            //非同步IO的核心物件名selector 具有事件偵聽的效果
            //selector就是您註冊對各種io事件的興趣的地方 而且當那些事件發生時 就是這個物件告訴您所發生的事情
            Selector selector=Selector.open();
            //開啟一個serversocketchannel通道
            ServerSocketChannel ssc=ServerSocketChannel.open();
            //設為非同步
            ssc.configureBlocking(false);
            //繫結埠
            ServerSocket ss=ssc.socket();
            InetSocketAddress address=new InetSocketAddress(5555);
            ss.bind(address);
            //註冊事件 regisiter的第一個引數總是selector 第二個總是op_accept 這裡他指定我們要監聽accept事件
            //也就是當有新的連結進來是發生的事件
            ssc.register(selector,SelectionKey.OP_ACCEPT);
            System.out.println("埠註冊完成");
            while(true){
                //select()這個方法會阻塞 直到有一個已註冊的事件發生 當一個或者更多的事件註冊進來的時候 這個會返回事件的數量
                selector.select();
                //呼叫selectedKeys()會返回事件物件集合
                Set<SelectionKey> selectionKeys=selector.selectedKeys();
                //然後我們迭代處理每一個事件
                Iterator<SelectionKey> iter=selectionKeys.iterator();
                ByteBuffer echoBuffer=ByteBuffer.allocate(20);
                SocketChannel sc;
                while(iter.hasNext()){
                    SelectionKey key=iter.next();
                    //判斷事件型別
                    if((key.readyOps()&SelectionKey.OP_ACCEPT)==SelectionKey.OP_ACCEPT)
                    {
                        ServerSocketChannel nssc=(ServerSocketChannel)key.channel();
                        sc=nssc.accept();
                        //設為非阻塞
                        sc.configureBlocking(false);
                        sc.register(selector, SelectionKey.OP_READ);
                        iter.remove();
                        System.out.println("有新的連結"+sc);
                    }else if((key.readyOps()&SelectionKey.OP_READ)==SelectionKey.OP_READ) {
                        sc=(SocketChannel)key.channel();
                        while(true){
                            echoBuffer.clear();
                            int a=sc.read(echoBuffer);
                            
                            if(a==-1)
                                break;
                            if(a>0){
                                byte[] b=echoBuffer.array();
                                System.out.println("接收資料: "+new String(b));
                                echoBuffer.flip();
                                sc.write(echoBuffer);
                                System.out.println("返回資料: "+new String(b));
                            }
                        }
                        sc.close();
                        System.out.println("連線結束");
                        System.out.println("=============================");
                        iter.remove();
                    }
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public static void main(String args[]){
        new Server().start();
    }
}

客戶端的程式碼

package org.web.niotest;

import java.net.*;
import java.nio.*;
import java.nio.channels.*;

public class Client {
    public void start() {
        try {
            SocketAddress address = new InetSocketAddress("localhost", 5555);
            SocketChannel client = SocketChannel.open(address);
            client.configureBlocking(false);
            String a = "asdasdasdasddffasfas";
            ByteBuffer buffer = ByteBuffer.allocate(20);
            buffer.put(a.getBytes());
            buffer.clear();
            int d = client.write(buffer);
            System.out.println("傳送資料: " + new String(buffer.array()));
            while (true) {
                buffer.flip();
                int i = client.read(buffer);
                if (i > 0) {
                    byte[] b = buffer.array();
                    System.out.println("接收資料: " + new String(b));
                    client.close();
                    System.out.println("連線關閉!");
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String args[]){
        new Client().start();
    }
}