我正在尝试使用 NIO 来构建一个高效的 Socket TCP/IP 服务器。
我有一个接受连接的主线程,然后将其添加到另一个线程,该线程应该等待来自客户端的消息然后读取它。
当我对所有操作只使用一个线程和一个选择器时,它工作得很好,但是当我试图让它与 2 个线程和 2 个选择器一起工作时,传入的连接接受正在工作,但读取不是,我认为它因为我的选择器阻塞了线程,因此他不知道我已经注册了一个新的 SocketChannel。
这是我的主线程:
public static void main(String[] args) {
try {
System.out.println("Who's Around Server Started!");
Selector connectionsSelector = null;
ServerSocketChannel server = null;
String host = "localhost";
int port = 80;
LiveConnectionsManager liveConnectionsManager =
new LiveConnectionsManager();
liveConnectionsManager.start();
connectionsSelector = Selector.open();
server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(host,port));
server.configureBlocking(false);
server.register(connectionsSelector, SelectionKey.OP_ACCEPT);
while (true) {
connectionsSelector.select();
Iterator<SelectionKey> iterator =
connectionsSelector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey incomingConnection = iterator.next();
iterator.remove();
if( incomingConnection.isConnectable()) {
((SocketChannel)incomingConnection.channel()).finishConnect();
}
if( incomingConnection.isAcceptable()){
acceptConnection(server.accept(), liveConnectionsManager);
}
}
}
} catch (Throwable e) {
throw new RuntimeException("Server failure: " + e.getMessage());
}
}
private static void acceptConnection(
SocketChannel acceptedConnection,
LiveConnectionsManager liveConnectionsManager ) throws IOException
{
acceptedConnection.configureBlocking(false);
acceptedConnection.socket().setTcpNoDelay(true);
System.out.println(
"New connection from: " + acceptedConnection.socket().getInetAddress());
liveConnectionsManager.addLiveConnection(acceptedConnection);
}
这是我的 LiveConnectionsManager:
private Selector messagesSelector;
public LiveConnectionsManager(){
try {
messagesSelector = Selector.open();
} catch (IOException e) {
System.out.println("Couldn't run LiveConnectionsManager");
}
}
@Override
public void run() {
try {
System.out.println("LiveConnectionManager Started!");
while(true) {
messagesSelector.select();
Iterator<SelectionKey> iterator = messagesSelector.keys().iterator();
while (iterator.hasNext()){
SelectionKey newData = iterator.next();
iterator.remove();
if( newData.isReadable()){
readIncomingData(((SocketChannel)newData.channel()));
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void addLiveConnection( SocketChannel socketChannel )
throws ClosedChannelException
{
socketChannel.register(messagesSelector, SelectionKey.OP_READ);
}