nio

package helloweenpad;

import java.io.FileInputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
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.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.Properties;

public class MyFirstNIOServer
{
   
    public static final int PORT=12315;
   
    protected Selector selector;
    protected Charset charset=Charset.forName("UTF-8");
    protected CharsetEncoder charsetEncoder=charset.newEncoder();
    protected CharsetDecoder charsetDecoder=charset.newDecoder();
   
    protected Properties talks=new Properties();
   
    int clientCount;
   
    public MyFirstNIOServer() throws Exception
    {
       
        talks.load(new FileInputStream("F:\\talk.properties"));
       
        selector=Selector.open();
       
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(PORT)); // port
        serverSocketChannel.configureBlocking(false);
       
        serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
        // register,为了获取SelectionKey的键
       
        p("Server localhost:"+PORT+" started. waiting for clients. ");
       
        while (true)
        {
            // selector 线程。select() 会阻塞,直到有客户端连接,或者有消息读入
            selector.select();
            Iterator<SelectionKey> iterator=selector.selectedKeys().iterator();
            while (iterator.hasNext())
            {               
                SelectionKey selectionKey=iterator.next();
                iterator.remove(); // 删除此消息
               
                // 并在当前线程内处理。(为了高效,一般会在另一个线程中处理此消息,例如使用线程池等)
                handleSelectionKey(selectionKey);
            }
        }
       
    }
   
    public void handleSelectionKey(SelectionKey selectionKey)
                                    throws Exception
    {
       
        if (selectionKey.isAcceptable())
        {
           
            // 有客户端进来
            clientCount++;
            ServerSocketChannel serverSocketChannel=(ServerSocketChannel)selectionKey.channel();
            SocketChannel socketChannel=serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            Socket socket=socketChannel.socket();
           
            // 立即注册一个 OP_READ 的SelectionKey, 接收客户端的消息
            SelectionKey key=socketChannel.register(selector,SelectionKey.OP_READ);
            key.attach("第 "+clientCount+" 个客户端 ["
                    +socket.getRemoteSocketAddress()+"]: ");
           
            p(key.attachment()
                    +"\t[connected] =========================================");
           
        } else
            if (selectionKey.isReadable())
            {
               
                // 有消息进来
               
                ByteBuffer byteBuffer=ByteBuffer.allocate(100);
                SocketChannel socketChannel=(SocketChannel)selectionKey.channel();
               
                try
                {
                    int len=socketChannel.read(byteBuffer);
                   
                    // 如果len>0,表示有输入。如果len==0, 表示输入结束。需要关闭
                    // socketChannel
                    if (len>0)
                    {
                       
                        byteBuffer.flip();
                        String msg=charsetDecoder.decode(byteBuffer).toString();
                       
                        // 根据客户端的消息,查找到对应的输出
                        String newMsg=talks.getProperty(msg)
                                    +"come from Server########\n";
                        if (newMsg==null)
                            newMsg="Sorry? I don't understand your message. ";
                       
                        // UTF-8 格式输出到客户端,并输出一个'n'
                       
                        socketChannel.write(charsetEncoder.encode(CharBuffer.wrap(newMsg
                                +"\n")));
                        p(selectionKey.attachment()
                                +"\t[recieved]: "
                                +msg
                                +" ----->\t[send]: "
                                +newMsg);
                       
                    } else
                    {
                        // 输入结束,关闭 socketChannel
                        p(selectionKey.attachment()
                                +"read finished. close socketChannel. ");
                        socketChannel.close();
                    }
                   
                } catch (Exception e)
                {
                   
                    // 如果read抛出异常,表示连接异常中断,需要关闭
                    // socketChannel
                    e.printStackTrace();
                   
                    p(selectionKey.attachment()
                            +"socket closed? ");
                    socketChannel.close();
                }
               
            } else
                if (selectionKey.isWritable())
                {
                    p(selectionKey.attachment()
                            +"TODO: isWritable() ???????????????????????????? ");
                } else
                    if (selectionKey.isConnectable())
                    {
                        p(selectionKey.attachment()
                                +"TODO: isConnectable() ????????????????????????? ");
                    } else
                    {
                        p(selectionKey.attachment()
                                +"TODO: else. ");
                    }
       
    }
   
    public static void p(Object object)
    {
        System.out.println("SSSSSSSSSSS"+object);
    }
   
    public static void main(String[] args) throws Exception
    {
        new MyFirstNIOServer();
    }
   
}

package helloweenpad;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Properties;
import java.util.Random;

public class MyFirstNIOClientTest extends Thread
{

    public static void main(String[] args) throws Exception
    {
       
        // 开三个客户端线程
        for (int i=0; i<3; i++)
        {
            try
            {
                new MyFirstNIOClientTest().start();
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
       
    }
   
    public static final String HOST="localhost";
    public static final int PORT=12315;
   
    boolean exist=false;
   
    Properties talks=new Properties();
    Random random=new Random();
    String[] keys;
   
    int messageCount=0;
   
    public void run()
    {
       
        try
        {
            // 对话内容
            talks.load(new FileInputStream("F:\\talk.properties"));
           
            // 客户端发送 "=" 左边的内容
            keys=new String[talks.size()];
            talks.keySet().toArray(keys);
           
            Socket socket=new Socket(HOST,PORT);
           
            OutputStream ous=socket.getOutputStream();
            InputStream ins=socket.getInputStream();
           
            // 接收线程,接收服务器的回应
            RecieverThread reciever=new RecieverThread(ins);
            reciever.start();
           
            while (!exist)
            {
               
                messageCount++;
               
                // 选择一个随机消息
                String msg=chooseMessage();
               
                synchronized (ins)
                {
                   
                    // 发送给服务器端
                    ous.write(msg.getBytes("UTF-8"));
                   
                    System.out.println("[send]\t"
                            +messageCount+": "+msg);
                   
                    // 然后等待接收线程
                    ins.wait();
                }
               
                if (msg.equals("Bye"))
                {
                    break;
                }
            }
           
            ins.close();
            ous.close();
            socket.close();
           
        } catch (Exception e)
        {
            System.out.print("建立新socket出现错误");
            e.printStackTrace();
        }
    }
   
    public String chooseMessage()
    {
       
        int index=random.nextInt(keys.length);
        String msg=keys[index];
       
        // 如果 10 次就选中 Bye,则重新选择,为了使对话内容多一些
        if (messageCount<10&&msg.equalsIgnoreCase("Bye"))
        {
            return chooseMessage();
        }
       
        return msg;
    }
   
    // 接收线程
    class RecieverThread extends Thread
    {
        private InputStream ins;
       
        public RecieverThread(InputStream ins)
        {
            this.ins=ins;
        }
       
        @Override
        public void run()
        {
           
            try
            {
                String line=null;
               
                BufferedReader r=new BufferedReader(new InputStreamReader(ins,"UTF-8"));
               
                // readLine()会阻塞,直到服务器输出一个 '\n'
                while ((line=r.readLine())!=null)
                {
                   
                    System.out.println("[Recieved]: "+line);
                   
                    synchronized (ins)
                    {
                        // 接收到服务器的消息,通知下主线程
                        ins.notify();
                    }
                    if (line.trim().equals("Bye"))
                    {
                        exist=true;
                        break;
                    }
                }
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
       
    }
   
}

posted on 2011-04-03 17:04  songqiuming  阅读(560)  评论(0编辑  收藏  举报

导航