`
AAries
  • 浏览: 38947 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

SocketChannel使用心得

 
阅读更多
1.服务器端while(true) 一直等待client端来连接。
  基本步骤为:
        ServerSocketChannel server = ServerSocketChannel.open();
        server.configureBlocking(false);

        server.socket().bind(new InetSocketAddress(5200));

        Selector select = Selector.open();
        server.register(select, SelectionKey.OP_ACCEPT);


声明一个等待客户端的服务器。
     select.select();
            Set readkeys = select.selectedKeys();
            Iterator iterator = readkeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = (SelectionKey) iterator.next();
                if (key.isAcceptable()) {
                    SocketChannel client = ((ServerSocketChannel) key.channel()).accept();
                    System.out.println("Accept connection from: " + client);
                    client.configureBlocking(false);
                    client.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }
                if (key.isReadable()) {

                    // 获得与客户端通信的信道
                    SocketChannel clientChannel = (SocketChannel) key.channel();

                    // 得到并清空缓冲区
                    ByteBuffer buffer = (ByteBuffer) key.attachment();
                    buffer.clear();

                    // 读取信息获得读取的字节数
                    long bytesRead = clientChannel.read(buffer);

                    if (bytesRead == -1) {
                        // 没有读取到内容的情况
                        clientChannel.close();
                    } else {
                        // 将缓冲区准备为数据传出状态
                        buffer.flip();

                        // 将字节转化为为UTF-16的字符串   
                        String receivedString = Charset.forName("UTF-16").newDecoder().decode(buffer).toString();

                        // 控制台打印出来
                        System.out.println("接收到来自" + clientChannel.socket().getRemoteSocketAddress() + "的信息:" + receivedString);

                        // 准备发送的文本
                        String sendString = "你好,客户端. @" + new Date().toString() + ",已经收到你的信息" + receivedString;
                        buffer = ByteBuffer.wrap(sendString.getBytes("UTF-16"));
                        clientChannel.write(buffer);

                        // 设置为下一次读取或是写入做准备
                        key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
                    }
                }
                if (key.isWritable())
                {
                    SocketChannel sc = (SocketChannel) key.channel();
                    ByteBuffer writeBuffer=ByteBuffer.wrap("我的程序员之道".getBytes("UTF-16"));
                    sc.write(writeBuffer);
                }
                key.channel().close();
            }

遍历键集,然后判断键的可读可写等做不同的操作

客户端建立一个线程,等待服务器端的回应:
1.建立基本的SocketChannel
       SocketChannel sc = SocketChannel.open(new InetSocketAddress("172.16.22.11", 5200));
        //打开一个SocketChannel并连接到服务器
        sc.configureBlocking(false);

        Selector selector = Selector.open();

        sc.register(selector, SelectionKey.OP_READ);


在实现Runable的run方法里遍历键集,判断做不同的操作:
while (selector.select() > 0) {
                // 遍历每个有可用IO操作Channel对应的SelectionKey
                Iterator it = selector.selectedKeys().iterator();
                while (it.hasNext()) {
                    SelectionKey sk = (SelectionKey) it.next();
                    it.remove();
                    // 如果该SelectionKey对应的Channel中有可读的数据
                    if (sk.isReadable()) {
                        // 使用NIO读取Channel中的数据
                        SocketChannel socketChannel = (SocketChannel) sk.channel();

                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        socketChannel.read(buffer);
                        buffer.flip();

                        // 将字节转化为为UTF-16的字符串   
                        String receivedString = Charset.forName("UTF-16").newDecoder().decode(buffer).toString();

                        // 控制台打印出来
                        System.out.println("接收到来自服务器" + socketChannel.socket().getRemoteSocketAddress() + "的信息:" + receivedString);

                        // 为下一次读取作准备
//                        sk.interestOps(SelectionKey.OP_READ);//将键设为可读

                    }
                    if (sk.isWritable()) {
                        SocketChannel socketChannel = (SocketChannel) sk.channel();
                        ByteBuffer writeBuffer = ByteBuffer.wrap("我的程序员之道".getBytes("UTF-16"));
                        socketChannel.write(writeBuffer);
                    }

                    // 删除正在处理的SelectionKey
                    selector.selectedKeys().remove(sk);
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
分享到:
评论
1 楼 kingj 2012-02-23  
你好,这个程序好像有问题,在我的windows xp上面跑不起来

相关推荐

Global site tag (gtag.js) - Google Analytics