您好我正在尝试实现一个简单的Java NIO服务器;它将socketChannel注册到选择器。因此,我希望听取客户的意见并发回一些回复。使用选择器注册socketChannel后,即使客户端(非NIO)发送了一些数据,服务器也无法读取; howerver生成的密钥仍在迭代中。
详细视图:服务器端:
**First thread**:
public void run(){ 而(真){
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(true);
serverSocketChannel.socket().bind(inetAdressOfServer);
SocketChannel clientChannel = serverSocketChannel.accept();
new Listener("").addSocketChannel(clientChannel);
}}
**Second Thread**:
static Selector selector = Selector.open();
public boolean addSocketChannel(SocketChannel clientChannel) {
SelectionKey key = clientSocketChannel.register(selector, selector.OP_READ|SelectionKey.OP_WRITE);
key.attach(new ChannelCallback(clientSocketChannel));
return key.isValid();
}
public void run() {
Set keysSet = selector.keys();
Iterator i = keysSet.iterator();
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
}
if (key.isReadable()) {
//read and do something
}
}
Client Side:
Socket socket = new Socket(serverIP, serverPort);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeBytes(str + "\n");
注意:当在单线程中完成时,相同的程序可以工作,但是当以上述方式实现时,会导致它不能监听客户端。 请帮我解决这个问题。
答案 0 :(得分:1)
很难看到你在那里做了什么,但看起来两个线程都使用了你标记为“第二线程”的内容(对实现Runnable
/扩展Thread
的一些困惑和实际的线程?)。特别是,我猜测new Listener
构造并启动一个线程。然后,您在第一个线程中调用addSocketChannel
。因此,存在竞争条件。
将selector
设为静态也是一个不好的主意。
答案 1 :(得分:1)
读取工作从另一个线程读取,这是您的代码的明显问题。
public void run() {
Set keysSet = selector.keys();
这里你从迭代器获取键集,但是没有代码在选择器上执行select()或selectNow(),所以这个set总是为空。
Iterator i = keysSet.iterator();
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
}
if (key.isReadable()) {
//read and do something
}
}
这甚至没有编译,关键的'read'检查必须在while块内完成。
SelectionKey key = clientSocketChannel.register(selector,
SelectionKey.OP_READ |
SelectionKey.OP_WRITE);
两个问题:在完成此操作之前,应将通道设置为非阻塞模式,并且不应设置SelectionKey.OP_WRITE,除非您希望每次运行select时都返回该键。
如果您实际上打算进行写操作,则只应设置SelectionKey.OP_WRITE。
最后,在这里使用两个线程非常不同寻常。建议的方法是使用OP_ACCEPT将ServerSocketChannel注册到Selector,并在与读/写相同的线程上运行ServerSocket上的accept。