SocketChannel 死循环在读消息

Busing 2009-12-11 10:27:06

/*
* 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();
os.write(mes.getBytes());
os.flush();
os.close();
s.close();

只发送给服务端一次消息 为什么客户端 死循环在 读消息呢?



这个是为什么,我没有一直在连接服务端阿!谁能解决下阿 谢谢拉



控制台信息



invoke startServer---------------------
nKeys=1
测试此键的通道是否已准备好接受新的套接字连接
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
nKeys=1
read a message from client!
。。。。。。

死循环下去了
...全文
755 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
ginhun 2012-04-29
  • 打赏
  • 举报
回复
我也遇到这个问题了,已经解决好了。

我和LZ的情况稍微有点不同的是,我在客户端用的是SocketChannel,LZ用的是Socket(应该差别不大吧,我也是刚接触,不是很懂的)。

问题出现的地方:
当断开客户端的SocketChannel,对应到LZ的代码就是:s.close(); ,服务器端就进入死循环了。

解决办法:
http://hi.baidu.com/leo_dare/blog/item/32832a4dba06f6c6d1c86ad6.html

在链接中原作者有说到了,
“当客户端的链接异常断开,此时代表这个链接的channel一直处于readable的状态,如何检查链接已断开呢?
一段时间的试验发现,链接断开后,虽然该channel的ready operation是OP_READ,但是此时channel.read(buffer)返回-1,此时可以增加一个判断”。
chenliuyang 2010-01-15
  • 打赏
  • 举报
回复
我也碰到了这个问题, 别人叫我在 读里面 注册写事件 , 死循环是没有读了, 但在写在死循环
boboo_2000_0 2009-12-11
  • 打赏
  • 举报
回复
问题出在下面代码上,如果不对条件进行判断,会一直循环下去,楼主要加上循环的结束代码才可以。

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!");
}
}
}
}
}

Busing 2009-12-11
  • 打赏
  • 举报
回复
你能和我说下 怎么改么?
应该不是跳出循环吧,应该在某断代码停在那里 等待客户端吧


我奇怪的是
为什么
nKeys = selector.select();
总是为1 应该是有一个客户来请求才会变成一阿,可是我请求一次,它就一直是 1

50,559

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧