I try to implement a UDP client server detection via broadcast. The idea is the following: I have a server, which is bound to port 12344 and a client which is bound to port 12345. Now, the client sends a broadcast package to 255.255.255.255 12344. The server should reply to this package with a other package to IPClient:12345.
The implementation uses Java nio.
The problem is, that on windows, the server gets the packages but cannot(?) send an answer (I don't see the answer in wireshark).
I have the following example code:
Client
public final class ASyncUDPClient {
public static void main(String[] args) throws IOException {
InetSocketAddress hostAddress = new InetSocketAddress("255.255.255.255", 12344);
System.out.println(hostAddress);
// Create a non-blocking socket channel
DatagramChannel channel = DatagramChannel.open();
channel.socket().setBroadcast(true);
channel.socket().bind(new InetSocketAddress(getAddress(), 12345));
channel.configureBlocking(false);
// Kick off connection establishment
channel.connect(hostAddress);
ByteBuffer buffer = getBuffer();
Selector selector = Selector.open();
channel.write(buffer);
System.out.println("data send");
channel.register(selector, SelectionKey.OP_READ);
while (true) {
final int select = selector.select();
System.out.println("select " + select);
Iterator selectedKeys = selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
System.out.println("key selected");
SelectionKey key = (SelectionKey) selectedKeys.next();
selectedKeys.remove();
if (!key.isValid()) {
continue;
}
if (key.isReadable()) {
System.out.println("read");
} else if (key.isWritable()) {
System.out.println("write");
}
}
}
}
private static ByteBuffer getBuffer() throws CharacterCodingException {
return Charset.forName("UTF-8").newEncoder().encode(CharBuffer.wrap("1234"));
}
private static InetAddress getAddress() throws SocketException {
final Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
NetworkInterface networkInterfaceToUse = null;
while (networkInterfaces.hasMoreElements()) {
final NetworkInterface networkInterface = networkInterfaces.nextElement();
if (networkInterface.getDisplayName().contains("Virtual")) continue;
if (networkInterface.isVirtual()) continue;
if (networkInterface.isLoopback()) continue;
if (!networkInterface.isUp()) continue;
networkInterfaceToUse = networkInterface;
System.out.println(networkInterfaceToUse);
}
return networkInterfaceToUse.getInterfaceAddresses().get(1).getAddress();
}
}
Server example
public class ASyncUDPSvr {
static int BUF_SZ = 1024;
static int port = 12344;
static public void main(String[] args) {
ASyncUDPSvr svr = new ASyncUDPSvr();
svr.process();
}
private static InetAddress getAddress() throws SocketException {
final Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
NetworkInterface networkInterfaceToUse = null;
while (networkInterfaces.hasMoreElements()) {
final NetworkInterface networkInterface = networkInterfaces.nextElement();
if (networkInterface.getDisplayName().contains("Virtual")) continue;
if (networkInterface.isVirtual()) continue;
if (networkInterface.isLoopback()) continue;
if (!networkInterface.isUp()) continue;
networkInterfaceToUse = networkInterface;
System.out.println(networkInterfaceToUse);
}
return networkInterfaceToUse.getInterfaceAddresses().get(1).getAddress();
}
private void process() {
try {
Selector selector = Selector.open();
DatagramChannel channel = DatagramChannel.open();
InetSocketAddress isa = new InetSocketAddress(getAddress(), port);
channel.socket().bind(isa);
channel.configureBlocking(false);
SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
clientKey.attach(new Con());
while (true) {
try {
selector.select();
Iterator selectedKeys = selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
try {
SelectionKey key = (SelectionKey) selectedKeys.next();
selectedKeys.remove();
if (!key.isValid()) {
continue;
}
if (key.isReadable()) {
read(key);
key.interestOps(SelectionKey.OP_WRITE);
} else if (key.isWritable()) {
write(key);
key.interestOps(SelectionKey.OP_READ);
}
} catch (IOException e) {
System.err.println("glitch, continuing... " + (e.getMessage() != null ? e.getMessage() : ""));
}
}
} catch (IOException e) {
System.err.println("glitch, continuing... " + (e.getMessage() != null ? e.getMessage() : ""));
}
}
} catch (IOException e) {
System.err.println("network error: " + (e.getMessage() != null ? e.getMessage() : ""));
}
}
private void read(SelectionKey key) throws IOException {
DatagramChannel chan = (DatagramChannel) key.channel();
Con con = (Con) key.attachment();
con.sa = chan.receive(con.req);
System.out.println("sender address: " + con.sa + "rcv: " + new String(con.req.array(), "UTF-8"));
con.resp = Charset.forName("UTF-8").newEncoder().encode(CharBuffer.wrap("send string"));
}
private void write(SelectionKey key) throws IOException {
DatagramChannel chan = (DatagramChannel) key.channel();
Con con = (Con) key.attachment();
System.out.println("sending data: " + new String(con.resp.array(), "UTF-8") + " to " + con.sa);
chan.send(con.resp, con.sa);
System.out.println("data send");
}
class Con {
ByteBuffer req;
ByteBuffer resp;
SocketAddress sa;
public Con() {
req = ByteBuffer.allocate(BUF_SZ);
}
}
}
InetSocketAddress hostAddress = new InetSocketAddress("255.255.255.255", 12344);
// ...
channel.connect(hostAddress);
The problem is here. You can't connect to the broadcast address, and in any case it doesn't make sense. The broadcast address isn't sending to you, you are sending to it. The server is sending to you from its own bind-address. Just remove this line. You will have to use DatagramChannel.send() rather than write(), as you are unconnected.
The accepted answer is not true. You can "connect" the channel to the broadcast address when you first set:
channel.socket().setBroadcast(true);
Of course UDP is a connectionless protocol, but a "connected" DatagramChannel has some benefits, one of them is the ability to use the write(ByteBuffer[]) method.
Related
I'm trying to send/recv a String using a Bytebuffer of fixed dimension, no matter what dimension is the string
Both client and server are composed by 2 classes, the main and the Client/Server, witch sould encapsulate the implementation of sending/receiving a string
For now the 2 main should work ad an echo client/server with the possibility of having multiple clients using a selector
Here is CLient side:
public class Client {
private SocketChannel clientChannel;
private int bufferDim;
public WinsomeClient(String host, int port, int bufferDim) throws IOException{
this.clientChannel = SocketChannel.open(new InetSocketAddress(host, port));
this.bufferDim = b.bufferDim;
System.out.println("Connected to " + b.serverHost + b.serverPort);
}
public String send(String request) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(bufferDim * Character.BYTES);
int iters = (int) Math.ceil(request.length / (float) bufferDim);
System.out.println("Iters: " + iters);
int offset = 0;
int length;
for(int i=0; i<iters; i++){
length = Math.min(bufferDim, request.length - offset);
buffer.put(request.getBytes(), offset, length);
buffer.flip();
while (buffer.hasRemaining()){
clientChannel.write(buffer);
}
buffer.clear();
offset += bufferDim;
}
System.out.println("Sent "+request.getMessage());
StringBuilder stringBuilder = new StringBuilder();
buffer.rewind();
while (clientChannel.read(buffer)>0){
buffer.flip();
while (buffer.hasRemaining()){
stringBuilder.append((char) buffer.get());
}
buffer.clear();
}
System.out.println("Recv" + stringBuilder.toString());
return stringBuilder.toString();
}
public class MainClient {
public static void main(String[] args) {
int port = 1919;
String host = "127.0.0.1";
int bufDim = 1024;
Client client ;
try{
client = new Client(host, port, bufDim);
for(String expected = "a"; ; expected+="a"){
System.out.println(expected);
String response = client.send(expected);
if(!response.equals(expected){
System.err.println("Expected " + expected + "; was " + response);
break;
}
System.out.println(response);
}
} catch (IOException e){
e.printStackTrace();
}
}
}
Server side:
public class Server {
private SocketChannel clientChannel;
private int bufferDim;
public WinsomeServer(SocketChannel clientChannel, int bufferDim){
this.clientChannel = clientChannel;
this.bufferDim = bufferDim;
}
public String recv() throws IOException{
ByteBuffer buffer = ByteBuffer.allocate(bufferDim * Character.BYTES);
buffer.rewind();
StringBuilder stringBuilder = new StringBuilder();
while (clientChannel.read(buffer)>0){
buffer.flip();
while (buffer.hasRemaining()){
stringBuilder.append((char) buffer.get());
}
buffer.clear();
}
System.out.println("Recv " + stringBuilder.toString());
return stringBuilder.toString();
}
public void send(String response) throws IOException{
ByteBuffer buffer = ByteBuffer.allocate(bufferDim * Character.BYTES);
buffer.rewind();
int iters = (int) Math.ceil(response.getMessageLength() / (float)bufferDim);
System.out.println("Iters: " + iters);
int offset = 0;
int length;
for(int i=0; i<iters; i++){
length = Math.min(bufferDim, response.getMessageLength()-offset);
buffer.put(response.getMessage().getBytes(), offset, length);
buffer.flip();
while (buffer.hasRemaining()){
clientChannel.write(buffer);
}
buffer.clear();
offset += bufferDim;
}
System.out.println("Sent "+ response.getMessage());
}
}
public class MainServer {
public static void main(String[] args) {
ServerSocketChannel serverChannel;
Selector selector = null;
ServerSocket serverSocket;
InetSocketAddress inetSocketAddress;
int port=1919;
System.out.println("Listening for connections on port " + port);
try{
serverChannel = ServerSocketChannel.open();
serverSocket = serverChannel.socket();
inetSocketAddress = new InetSocketAddress(port);
serverSocket.bind(inetSocketAddress);
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e){
e.printStackTrace();
return;
}
while (true){
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
try {
if(key.isAcceptable()){
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
}
else if(key.isReadable()){
System.out.println("Reading...");
SocketChannel client = (SocketChannel) key.channel();
Server server = new Server(client);
String request = server.recv();
SelectionKey key1 = client.register(selector, SelectionKey.OP_WRITE);
key1.attach(request);
}
else if(key.isWritable()){
System.out.println("Writing...");
SocketChannel client = (SocketChannel) key.channel();
Server server = new Server(client);
String request = (String) key.attachment();
request.append("Echoed by server");
server.send(request);
client.register(selector, SelectionKey.OP_READ);
}
}
catch (IOException e){
key.cancel();
try {
key.channel().close();
} catch (IOException ee){
}
}
iterator.remove();
}
}
}
}
However, after receiving the string and sending it back, the client is not recieving it.
Anyone can figure out where is the problem?
Server output:
Listening for connections on port 1919
Accepted connection from java.nio.channels.SocketChannel[connected local=/127.0.0.1:1919 remote=/127.0.0.1:51504]
Reading...
Recv a
Writing...
Writing... a1
Iters: 1
Sent a
Reading...
Client output:
Connected to 127.0.0.11919
a
Iters: 1
Sent a
I am trying to write a simple client/server in Java using NIO and Selectors. The server is very easy and it's the most typical implementation that you can find everywhere. Here's the code of the server (look at the start() method):
public final class MyServer {
private int port;
private String address;
public MyServer(String address, int port) {
this.address = address;
this.port = port;
}
public void start() throws IOException {
try {
Selector selector = Selector.open();
ServerSocketChannel socket = ServerSocketChannel.open();
InetSocketAddress addr = new InetSocketAddress(address, port);
socket.bind(addr);
socket.configureBlocking(false);
boolean isAlive = true;
SelectionKey selectKy = socket.register(selector, SelectionKey.OP_ACCEPT, null);
while (isAlive) {
selector.select();
Set<SelectionKey> keysList = selector.selectedKeys();
Iterator<SelectionKey> keys = keysList.iterator();
while (keys.hasNext()) {
SelectionKey theKey = keys.next();
if (theKey.isAcceptable()) {
SocketChannel clientSocket = socket.accept();
clientSocket.configureBlocking(false);
clientSocket.register(selector, SelectionKey.OP_READ);
}
if (theKey.isReadable()) {
SocketChannel clientSocket = (SocketChannel) theKey.channel();
ByteBuffer buffer = ByteBuffer.allocate(9000);
clientSocket.read(buffer);
String result = new String(buffer.array()).trim();
System.out.println(" > SERVER: Request from " + clientSocket.getLocalAddress() + " [ toValidate = " + result + " ], sending tokens...");
//Now I send to the client a list
buffer.flip();
for (int i = 0; i < 5; ++i)
buffer.put((byte) getRandom(1, 10));
clientSocket.write(buffer);
buffer.clear();
System.out.println(" > SERVER: Response successfully sent");
}
keys.remove();
}
}
} catch (Exception e) {
System.out.println("[ SERVER ALERT: " + e.getMessage() + " ]");
}
}
}
As you can see, the code is pretty basic. Inside the if (theKey.isReadable()) I try to read a small string from the client, I print it to the console, then I flip the buffer and I send some data back to the client.
Here we have the client that sadly has a problem I cannot find:
public void something() throws IOException, InterruptedException {
ByteBuffer buffer = ByteBuffer.allocate(9000);
//Note that mRequests is a List of strings
try (SocketChannel client = SocketChannel.open(new InetSocketAddress(authIPAddr, authPort));) {
//For each transaction in mRequests, get the tokens from the server and verify them
for (String s : mRequests) {
//Write the string to the buffer and send the string
buffer.put(s.getBytes());
client.write(buffer);
buffer.rewind();
//Get response from the server
client.read(buffer);
buffer.clear();
Thread.sleep(1000);
}
}
}
The problem is exactly here:
buffer.put(s.getBytes());
client.write(buffer);
buffer.rewind();
I can say that the problem is there because the server should print
SERVER: Request from /127.0.0.1:2323 [ toValidate = {some_value} ], sending
tokens...
but instead it prints
SERVER: Request from /127.0.0.1:2323 [ toValidate = ], sending
tokens...
and from this I guess that data arent sent to the server. How can I solve this?
I have some server and client code that use nio in java. When I try connected to the server sctpChannel.connect(new InetSocketAddress("127.0.0.1",4545)); returns false. And selector.select() returns 0 . I can't figure out why it happens.
public class SctpNioServer {
public static void main(String[] args)throws Exception{
InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost",4545);
SctpServerChannel serverChannel = SctpServerChannel.open();
serverChannel.bind(inetSocketAddress);
serverChannel.configureBlocking(false);
Selector selector = Selector.open();
serverChannel.register(selector,SelectionKey.OP_ACCEPT );
while(true){
try{
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys() ;
Iterator<SelectionKey> iterator = selectedKeys.iterator();
while (iterator.hasNext()){
SelectionKey key = iterator.next();
iterator.remove();
if(key.isAcceptable()){
SctpChannel channel = serverChannel.accept();
channel.configureBlocking(false) ;
channel.register(selector,SelectionKey.OP_READ);
}
if (key.isReadable()){
SctpChannel channel = (SctpChannel) key.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
channel.receive(byteBuffer,null,null);
byteBuffer.flip();
while (byteBuffer.hasRemaining()){
System.out.println((char)byteBuffer.get());
}
byteBuffer.clear();
channel.register(selector, SelectionKey.OP_WRITE);
}
if(key.isWritable()){
//doSomething
}
}
selector.wakeup();
}
catch (IOException e){
e.printStackTrace();
}
finally {
serverChannel.close();
}
}
}}
public class SctpNioClient {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
SctpChannel channel = SctpChannel.open();
channel.configureBlocking(false);
channel.connect(new InetSocketAddress("localhost", 4545));
Selector sel = Selector.open();
channel.register(sel, SelectionKey.OP_CONNECT);
while (true) {
if (sel.isOpen()) {
int keys = sel.select(5);
if (keys > 0) {
Set<SelectionKey> selectedKeys = sel.selectedKeys();
for (SelectionKey sk : selectedKeys) {
if (!sk.isValid()) {
break;
}
if (sk.isConnectable()) {
channel.finishConnect();
channel.register(sel, SelectionKey.OP_WRITE, channel);
}
if (sk.isWritable()) {
SctpChannel ch = (SctpChannel) sk.channel();
System.out.println("writing->");
ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
String text = scanner.nextLine();
byteBuffer.clear();
byteBuffer.put(text.getBytes());
byteBuffer.flip();
MessageInfo messageInfo = MessageInfo.createOutgoing(null,null,0);
ch.send(byteBuffer,messageInfo);
ch.register(sel , SelectionKey.OP_READ);
sel.wakeup();
}
if(sk.isReadable()){
SctpChannel ch = (SctpChannel) sk.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
ch.receive(byteBuffer,null,null);
byteBuffer.flip();
while (byteBuffer.hasRemaining()){
System.out.println((char)byteBuffer.get());
}
ch.register(sel,SelectionKey.OP_WRITE);
} } } } }
} catch (IOException ex) { }
}}
connect() returns a boolean. You claim that it is false, but your code ignores it.
If it returns true, you don't need to register for OP_CONNECT: but as you are ignoring it you are also ignoring this fact.
finishConnect() also returns a boolean, which you are also ignoring.
All these operations can throw IOExceptions, which you are also ignoring.
Solution: don't. In all cases.
I am reading following tutorial:
http://tutorials.jenkov.com/java-nio/selectors.html
I am feeling that I am didn't understand a lot of details of following article but I am trying to invoke example at the end of the article.
my final code looks so:
public static void main(String[] args) throws IOException {
ServerSocketChannel channel = ServerSocketChannel.open();
Selector selector = Selector.open();
channel.configureBlocking(false);
SelectionKey selectionKey = channel.register(selector, SelectionKey.OP_READ);
while (true) {
int readyChannels = selector.select();
if (readyChannels == 0) continue;
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();//cause of exception
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
// a connection was accepted by a ServerSocketChannel.
} else if (key.isConnectable()) {
// a connection was established with a remote server.
} else if (key.isReadable()) {
// a channel is ready for reading
} else if (key.isWritable()) {
// a channel is ready for writing
}
keyIterator.remove();
}
}
}
As a result of this method invokation I see follwing stacktrace:
Exception in thread "main" java.lang.IllegalArgumentException
at java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSelectableChannel.java:196)
at java.nio.channels.SelectableChannel.register(SelectableChannel.java:277)
...
update
my full code variant:
public class NioSelectorTest {
public static void main(String[] args) {
new Thread(new Receiver()).start();
new Thread(new Sender()).start();
}
}
class Receiver implements Runnable {
private static byte[] data = new byte[255];
public void run() {
try {
for (int i = 0; i < data.length; i++)
data[i] = (byte) i;
ServerSocketChannel server = ServerSocketChannel.open();
server.configureBlocking(false);
server.socket().bind(new InetSocketAddress(9000));
Selector selector = Selector.open();
server.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Set readyKeys = selector.selectedKeys();
Iterator iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = (SelectionKey) iterator.next();
iterator.remove();
if (key.isAcceptable()) {
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
ByteBuffer source = ByteBuffer.wrap(data);
SelectionKey key2 = client.register(selector, SelectionKey.OP_WRITE);
key2.attach(source);
} else if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
if (!output.hasRemaining()) {
output.rewind();
}
client.write(output);
}
key.channel().close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Sender implements Runnable {
public void run() {
try {
SocketChannel sChannel = SocketChannel.open();
sChannel.configureBlocking(false);
sChannel.connect(new InetSocketAddress("localhost", 9000));
while (!sChannel.finishConnect()) {
ByteBuffer buf = ByteBuffer.allocateDirect(1024);
buf.put((byte) 0xFF);
buf.flip();
int numBytesWritten = sChannel.write(buf);
System.out.println("sent " + numBytesWritten + " bytes");
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
}
In console I see
Accepted connection from java.nio.channels.SocketChannel[connected
local=/127.0.0.1:9000 remote=/127.0.0.1:50940]
In debug I see that I cannot to enter into this loop:
while (!sChannel.finishConnect()) {
...
SelectionKey selectionKey = channel.register(selector, SelectionKey.OP_READ);
This should be OP_ACCEPT for a ServerSocketChannel.
In Java documentation it's written that register method throws
IllegalArgumentException - If a bit in ops does not correspond to an operation that is supported by this channel, that is, if set & ~validOps() != 0
(Source: http://bit.ly/1lSBdX8)
I think you need to bind a specific port at first, and register selector on that SocketChannel. So the beginning of your code should look like this:
ServerSocketChannel channel = ServerSocketChannel.open();
channel.socket().bind(new InetSocketAddress(8080)); // 8080 is the port you'll be listening
SocketChannel socketChannel = serverSocketChannel.accept();
Selector selector = Selector.open();
socketChannel.configureBlocking(false);
SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);
...
I'm trying to write a chat server and client that uses sockets. Connecting the client works properly and I get the correct output from the server:
Listening on port 8000
Got connection from Socket[addr=/127.0.0.1,port=50628,localport=8000]
But when I send something from the client I get IllegalBlockingModeException. Here's what I have:
public void listen()
{
try {
// Open a non-blocking socket channel
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
// Get the socket and bind it
ServerSocket ss = ssc.socket();
InetSocketAddress isa = new InetSocketAddress(this.getServerName(), this.getServerPort());
ss.bind(isa);
// Create the selector
Selector selector = Selector.open();
ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Listening on port " + this.getServerPort());
while (true)
{
// Wait for at least one channel to be selected
if (selector.select() == 0)
continue;
// Iterate the key set and dispatch messages
Set keys = selector.selectedKeys();
Iterator it = keys.iterator();
while (it.hasNext())
{
SelectionKey key = (SelectionKey)it.next();
if (key.isAcceptable()) {
Socket s = ss.accept();
System.out.println("Got connection from " + s);
SocketChannel sc = s.getChannel();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
}
else if (key.isReadable()) {
SocketChannel sc = null;
try {
sc = (SocketChannel)key.channel();
String message = processInput(sc);
if (message == null) {
key.cancel();
Socket s = null;
try {
s = sc.socket();
System.out.println("Closing connection to " +s);
s.close();
} catch( IOException ie ) {
System.err.println("Error closing socket " + s + ": " + ie);
}
}
else {
String response = getListener().process(sc, message);
ObjectOutputStream oos = new ObjectOutputStream(Channels.newOutputStream(sc));
//ObjectOutputStream oos = new ObjectOutputStream(sc.socket().getOutputStream());
oos.writeObject(response + "\n");
oos.close();
}
}
catch(IOException ie) {
key.cancel();
try {
sc.close();
} catch(IOException ie2) {
System.out.println(ie2);
}
System.out.println("Closed " + sc);
}
}
}
keys.clear();
}
}
catch (IOException ex) {
System.out.println(ex);
System.exit(1);
}
}
private String processInput( SocketChannel sc ) throws IOException {
buffer.clear();
sc.read( buffer );
buffer.flip();
if (buffer.limit()==0) {
return null;
}
return decoder.decode(buffer).toString();
}
Here's the stack trace:
java.nio.channels.SocketChannel[connected local=/127.0.0.1:8000 remote=/127.0.0.1:50656]
Exception in thread "main" java.nio.channels.IllegalBlockingModeException
at java.nio.channels.Channels.writeFully(Channels.java:97)
at java.nio.channels.Channels.access$000(Channels.java:61)
at java.nio.channels.Channels$1.write(Channels.java:174)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1870)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1779)
at java.io.ObjectOutputStream.<init>(ObjectOutputStream.java:247)
at ChatServer$Server.listen(ChatServer.java:171)
at ChatServer.run(ChatServer.java:231)
at ChatServer.main(ChatServer.java:247)
Java Result: 1
Does anybody know how to solve this?
You can't use Channels.newXXXStream() on a channel in non-blocking mode. See the Javadoc.
Ok, I managed to put it to work. Here's how:
String response = getListener().process(sc, message) + "\n";
ByteBuffer bb = ByteBuffer.wrap(response.getBytes("utf-8"));
sc.write(bb);
Instead of using an OutputStream, write directly to the SocketChannel.