日期:2014-05-20  浏览次数:20836 次

SocketChannel 死循环在读消息
Java code

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package testsocketchannel;

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
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 java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author root
 */
public class Main implements Runnable {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        // TODO code application logic here
        //启动  serversockechannel
        Main main=new Main();
        Thread t=new Thread(main);
        t.start();


        //休眠,防止server没有及时启动
        Thread.sleep(1000);


        //连接server 发送消息
        String mes="send a message";
        Socket s=new Socket("127.0.0.1", 9000);
        OutputStream os=s.getOutputStream();
        os.write(mes.getBytes());
        os.flush();
        os.close();
        s.close();
        
    }





    //start server
     public void run(){
        try {
            Selector selector;
            ServerSocketChannel ssc;
            SocketChannel sc;
            boolean stop = true;
            System.out.println("invoke startServer---------------------");
            int nKeys = 0;
            selector = Selector.open(); // 打开一个选择器
            ssc = ServerSocketChannel.open(); //打开服务器套接字通道。
            InetSocketAddress add = new InetSocketAddress(9000);
            ssc.socket().bind(add);
            ssc.configureBlocking(false); //调整此通道的阻塞模式 true为阻塞 false为非阻塞
            SelectionKey seletK = ssc.register(selector, SelectionKey.OP_ACCEPT); //向给定的选择器注册此通道,返回一个选择键。
            while (stop) {
                synchronized (this) {
                    nKeys = selector.select(); //选择一组键,其相应的通道已为 I/O 操作准备就绪。返回已更新其准备就绪操作集的键的数目、
                    System.out.println("nKeys=" + nKeys);
                    if (nKeys > 0) {
                        Set<SelectionKey> selectedKeys = selector.selectedKeys(); //返回此选择器的已选择键集。
                        Iterator i = selectedKeys.iterator(); //返回在此 set 中的元素上进行迭代的迭代器
                        while (i.hasNext()) {
                            //如果仍有元素可以迭代,则返回 true
                            seletK = (SelectionKey) i.next(); //返回迭代的下一个元素。
                            i.remove();
                            if (seletK.isAcceptable()) {
                                //测试此键的通道是否已准备好接受新的套接字连接
                                System.out.println("测试此键的通道是否已准备好接受新的套接字连接");
                                Socket socket = ((ServerSocketChannel) seletK.channel()).accept().socket(); //  获取与此通道关联的套接字。
                                sc = socket.getChannel(); //返回与此数据报套接字关联的唯一 SocketChannel 对象
                                sc.configureBlocking(false);
                                sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
                            }
                            if (seletK.isReadable()) {
                                //测试此键的通道是否已准备好进行读取。
                                System.out.println("read a message from client!");
                            }
                        }
                    }
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}







这段代码 执行的时候出现了这样的问题, 我代码
  //连接server 发送消息
  String mes="send a message";
  Socket s=new Socket("127.0.0.1", 9000);
  OutputStream os=s.getOutputStream();