-
-
Save Botffy/3860641 to your computer and use it in GitHub Desktop.
package niochat; | |
import java.net.*; | |
import java.nio.*; | |
import java.nio.channels.*; | |
import java.io.IOException; | |
import java.util.*; | |
public class NiochatServer implements Runnable { | |
private final int port; | |
private ServerSocketChannel ssc; | |
private Selector selector; | |
private ByteBuffer buf = ByteBuffer.allocate(256); | |
NiochatServer(int port) throws IOException { | |
this.port = port; | |
this.ssc = ServerSocketChannel.open(); | |
this.ssc.socket().bind(new InetSocketAddress(port)); | |
this.ssc.configureBlocking(false); | |
this.selector = Selector.open(); | |
this.ssc.register(selector, SelectionKey.OP_ACCEPT); | |
} | |
@Override public void run() { | |
try { | |
System.out.println("Server starting on port " + this.port); | |
Iterator<SelectionKey> iter; | |
SelectionKey key; | |
while(this.ssc.isOpen()) { | |
selector.select(); | |
iter=this.selector.selectedKeys().iterator(); | |
while(iter.hasNext()) { | |
key = iter.next(); | |
iter.remove(); | |
if(key.isAcceptable()) this.handleAccept(key); | |
if(key.isReadable()) this.handleRead(key); | |
} | |
} | |
} catch(IOException e) { | |
System.out.println("IOException, server of port " +this.port+ " terminating. Stack trace:"); | |
e.printStackTrace(); | |
} | |
} | |
private final ByteBuffer welcomeBuf = ByteBuffer.wrap("Welcome to NioChat!\n".getBytes()); | |
private void handleAccept(SelectionKey key) throws IOException { | |
SocketChannel sc = ((ServerSocketChannel) key.channel()).accept(); | |
String address = (new StringBuilder( sc.socket().getInetAddress().toString() )).append(":").append( sc.socket().getPort() ).toString(); | |
sc.configureBlocking(false); | |
sc.register(selector, SelectionKey.OP_READ, address); | |
sc.write(welcomeBuf); | |
welcomeBuf.rewind(); | |
System.out.println("accepted connection from: "+address); | |
} | |
private void handleRead(SelectionKey key) throws IOException { | |
SocketChannel ch = (SocketChannel) key.channel(); | |
StringBuilder sb = new StringBuilder(); | |
buf.clear(); | |
int read = 0; | |
while( (read = ch.read(buf)) > 0 ) { | |
buf.flip(); | |
byte[] bytes = new byte[buf.limit()]; | |
buf.get(bytes); | |
sb.append(new String(bytes)); | |
buf.clear(); | |
} | |
String msg; | |
if(read<0) { | |
msg = key.attachment()+" left the chat.\n"; | |
ch.close(); | |
} | |
else { | |
msg = key.attachment()+": "+sb.toString(); | |
} | |
System.out.println(msg); | |
broadcast(msg); | |
} | |
private void broadcast(String msg) throws IOException { | |
ByteBuffer msgBuf=ByteBuffer.wrap(msg.getBytes()); | |
for(SelectionKey key : selector.keys()) { | |
if(key.isValid() && key.channel() instanceof SocketChannel) { | |
SocketChannel sch=(SocketChannel) key.channel(); | |
sch.write(msgBuf); | |
msgBuf.rewind(); | |
} | |
} | |
} | |
public static void main(String[] args) throws IOException { | |
NiochatServer server = new NiochatServer(10523); | |
(new Thread(server)).start(); | |
} | |
} |
why netty came when java nio is doing same thing...?
I have a stupid question:
As we know we use NIO in case there is a lot of connections and we use Selector to manage these connections via Channels
So, when we should use Stream IO?
Because nio is non-blocking, so doesn't require additional threads. A socket-based chat would require as many threads as there are users, adding a significant overhead, while a nio chat would always need but one thread, making it a lot more scalable, as the overhead of threading may get really significant.
Not necessarily. In actual measurements in Java on Linux, multithreaded
classic I/O designs outperform NIO by 30% or so. [see@Java Network Programming Book]
Java NIO outperforms a classic I/O design only if
- You have a huge amount auf clients >20.000
- Interval between data packages to send is very short.
Conclusion: You need a Server for >20.000 Clients with high frequently communication.
But as Tutorial your Chat Server Example is good.
how i can do a long polling server with java.nio?