我的简单Java NIO客户端-服务器非阻塞连接无法工作
我正在尝试使用一个简单的客户机-服务器程序,最终目标是实现双向通信。由于某种原因,当我只是实例化客户机类以使其连接到服务器而不发送任何数据时,它不起作用,并引发无法建立环回连接异常。当我通过stdin进行一个while循环读取时,它就工作了。我需要先建立连接,然后每隔一段时间向服务器发送一条消息。我怎样才能修好它 客户端代码:我的简单Java NIO客户端-服务器非阻塞连接无法工作,java,nio,Java,Nio,我正在尝试使用一个简单的客户机-服务器程序,最终目标是实现双向通信。由于某种原因,当我只是实例化客户机类以使其连接到服务器而不发送任何数据时,它不起作用,并引发无法建立环回连接异常。当我通过stdin进行一个while循环读取时,它就工作了。我需要先建立连接,然后每隔一段时间向服务器发送一条消息。我怎样才能修好它 客户端代码: import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBu
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
public class ClientCore {
SelectionKey selkey;
Selector sckt_manager ;
SocketChannel sc;
public ClientCore() {
try {
sc = SocketChannel.open();
sc.configureBlocking(false);
sc.connect(new InetSocketAddress(8888));
// should not proceed until connect is finished
while (!sc.finishConnect()) {
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (sc != null) {
try {
sc.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
void send(String message) {
try {
if (!message.equalsIgnoreCase("end")) {
System.out.println("Sending a request to the server ...");
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
sc.write(buffer);
}
} catch (IOException e) {
}
}
public static void main(String[] args) throws Exception {
ClientCore cl = new ClientCore();
cl.send("hello");
}
}
服务器代码:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.channels.spi.SelectorProvider;
public class ServerCore extends Thread {
SelectionKey selkey = null;
Selector sckt_manager = null;
public void run() {
try {
coreServer();
} catch (Exception ej) {
ej.printStackTrace();
}
}
private void coreServer() {
try {
ServerSocketChannel ssc = ServerSocketChannel.open();
try {
ssc.socket().bind(new InetSocketAddress(8888));
while (true) {
sckt_manager = SelectorProvider.provider().openSelector();
ssc.configureBlocking(false);
SocketChannel sc = ssc.accept();
register_server(ssc, SelectionKey.OP_ACCEPT);
if (sc == null) {
} else {
System.out
.println("Received an incoming connection from "
+ sc.socket().getRemoteSocketAddress());
printRequest(sc);
System.err.println("testing 1");
String HELLO_REPLY = "Sample Display";
ByteBuffer buffer = ByteBuffer.wrap(HELLO_REPLY .getBytes());
System.err.println("testing 2");
sc.write(buffer);
System.err.println("testing 3");
sc.close();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ssc != null) {
try {
ssc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (Exception E) {
System.out.println("Ex in servCORE " + E);
}
}
private static void printRequest(SocketChannel sc) throws IOException {
ReadableByteChannel rbc = Channels.newChannel(sc.socket()
.getInputStream());
WritableByteChannel wbc = Channels.newChannel(System.out);
ByteBuffer b = ByteBuffer.allocate(1024); // read 1024 bytes
while (rbc.read(b) != -1) {
b.flip();
while (b.hasRemaining()) {
wbc.write(b);
System.out.println();
}
b.clear();
}
}
public void register_server(ServerSocketChannel ssc, int selectionkey_ops)
throws Exception {
ssc.register(sckt_manager, selectionkey_ops);
}
public static void main(String[] args) {
ServerCore st = new ServerCore();
st.coreServer();
}
}
这不是异步代码。它是非阻塞代码。您的连接代码完全等同于在设置非阻塞模式之前进行连接,只是后者不会占用CPU。您不需要每次在循环中都使用新的选择器,也不需要将ServerSocketChannel设置为非阻塞模式:而且由于您不使用选择器,因此很难理解为什么要使用选择器。这段代码没有多大意义。你学习过Oracle NIO教程吗?我遵循了Stackoverflow帖子中的一个示例代码:只要我们有一个从stdin读取的循环,它就可以工作,而当循环单独位于另一个函数中时,它就不工作了!如果我们要集中修改它,让我放另一个我尝试过的代码。我怎么能使它异步呢?我不知道你到底为什么要从问题中复制代码。你应该从答案中复制它。这是胡说八道,答案是在别处引用OP。我也只能这样做。您可以通过将其全部丢弃并使用AsynchronousSocketChannel和friends来实现异步,但为什么呢?您的实际目标是什么?“队列中的每一方轮询消息”正在忙着等待。你把四件不同的事情混为一谈:1忙着等待;2个阻塞I/O,3个非阻塞I/O;4异步I/O。除了可以通过1实现2之外,没有两个是相同的。