在使用socket的非阻塞模式中,ServerSocketChannel执行了联接就绪事件之后程序自动结束,不继续进行可读事件和可写事件

在使用socket的非阻塞模式中,ServerSocketChannel执行了连接就绪事件之后程序自动结束,不继续进行可读事件和可写事件
本帖最后由 u012286237 于 2014-09-23 20:07:03 编辑
最近在使用NIO的时候,使用非阻塞的socket进行服务器和客户端数据交互的时候,出现了当客户端和服务器连接成功之后,服务器端程序就直接结束了,而不进入可读就绪事件和可写就绪事件,那位高人可以出来指点一二,感激不尽了。以下分别是非阻塞的客户端类,服务器端,还有线程池中的类,不好意思,直接写在原帖中超过字符数了,服务器端和其他代码回复在1楼了
package com.BlockThreadTest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * @author swallretu
 * 非阻塞的客户端类
 */
public class UnBlockExecutorClient {

private Selector selector = null;//创建一个事件选择器
private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);//用来存储向服务器发送消息的buffer
private ByteBuffer reciveBuffer = ByteBuffer.allocate(1024);//用来接收服务器返回消息的buffer
private SocketChannel socketChannel = null; //创建一个SocketChannel
private Charset charest = Charset.forName("GBK"); //创建一个字符集


public UnBlockExecutorClient() throws Exception{
socketChannel = SocketChannel.open(); //生成socketChannel
InetAddress ia = InetAddress.getLocalHost(); //得到本地ip
InetSocketAddress is = new InetSocketAddress(ia, 11113); //绑定ip和端口到socket
socketChannel.connect(is);
socketChannel.configureBlocking(false);//设置socketchannel是非阻塞的socket
System.out.println("服务器已经连接");
selector = Selector.open(); //生成事件选择器
}

public static void main(String[] args) throws Exception{
final UnBlockExecutorClient unBlockClient = new UnBlockExecutorClient();
Thread thread = new Thread(){
public void run(){
unBlockClient.reciveMessageFromKeyBoard();
}
};

thread.start(); //启动接收客户端向服务器发送消息的线程
unBlockClient.talk(); //开始客户端和服务器的对话

}

/**
 * @Description
 *  客户端和服务器交互消息
 */
public void talk() throws Exception{
socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);//向事件选择器中注入事件
while(selector.select()>0){
Set keySet = selector.keys();
Iterator iterator = keySet.iterator();
while(iterator.hasNext()){
SelectionKey key = null;
try {
key = (SelectionKey) iterator.next();
iterator.remove();
if(key.isReadable()){
recive(key);//读准备就绪开始接收消息
}
if(key.isWritable()){
sendToClient(key);//写准备就绪发送消息
}
} catch (Exception e) {
// TODO Auto-generated catch block
if(key !=null){
key.cancel(); //清空事件
key.channel().close();//关闭和事件关联的channel
}
}
}
}
}

/**
 * @Description
 *  接收从键盘输入的消息
 */
public void reciveMessageFromKeyBoard(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String recive_msg = "";
while(true){
System.out.println("请向服务器发送消息:");

try {
recive_msg = reader.readLine();//读取向服务器发送的消息
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

synchronized (sendBuffer) {

//将要发到服务器的消息,放入到sendBuffer中;加锁是因为在写准备就绪事件中调用的也是将sendBuffer对象发送到服务器,所以为了线程同步安全所以加了锁
sendBuffer.put(encode(recive_msg));
}
if(recive_msg.equals("bye")){
break;
}
}
}

/**
 * @param 准备就绪的事件
 * @向客户端发送消息
 */
public void sendToClient(SelectionKey key) throws Exception{
SocketChannel socketChannel = (SocketChannel) key.channel();//得到socketChannel
synchronized (sendBuffer) {
sendBuffer.flip(); //把极限设为位置,把位置设为零
socketChannel.write(sendBuffer); //将要发送的消息写入socketChannel中
sendBuffer.compact();//将buffer中已发送的数据删除
}
}

/**
 * @param 准备就绪的事件
 * @接收服务器返回的消息
 */
public void recive(SelectionKey key){
SocketChannel socketChannel = (SocketChannel) key.channel(); //得到socketChannel

try {
socketChannel.read(reciveBuffer);//将socketChannel接收到消息读入到reciveBuffer中
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

reciveBuffer.flip();
String recive_msg = decode(reciveBuffer);
if(recive_msg.indexOf("\n")==-1){