Re: the best practise of udpchannel with selector??
Ok, I wrote the code like this:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
public class UDPSender implements Runnable {
private Thread thread;
private boolean run;
private DatagramChannel channel;
private Selector selector;
private SelectionKey mykey;
private ConcurrentLinkedQueue<String> queue = new
ConcurrentLinkedQueue<String>();
private String ip = "192.168.43.158";
private int port = 2222;
public UDPSender() {
run = true;
try {
channel = DatagramChannel.open();
channel.configureBlocking(false);
selector = Selector.open();
mykey=channel.register(selector, SelectionKey.OP_READ|
SelectionKey.OP_WRITE);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new InstantiationError();
}
}
public void start() {
thread = new Thread(this);
thread.start();
}
public void send(){
queue.add("sadfasdf");
selector.wakeup();
}
public void run() {
// TODO Auto-generated method stub
try {
while (run) {
if(!queue.isEmpty()){
mykey.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE);
}
selector.select();
Iterator<SelectionKey> iter = selector.selectedKeys()
.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
handle(key);
iter.remove();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void handle(SelectionKey key) {
if (key.isReadable()) {
System.out.println("there are something to read");
ByteBuffer k=ByteBuffer.allocate(1000);
try {
channel.receive(k);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("received: --"+new String(k.array(),
0,k.position())+"--");
}
if (key.isWritable()) {
ByteBuffer x = ByteBuffer.wrap("hello".getBytes());
Iterator<String> iter = queue.iterator();
while (iter.hasNext()) {
System.out.println("I send!");
String k=iter.next();
try {
channel.send(x, new InetSocketAddress(ip, port));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
queue.clear();
key.interestOps(SelectionKey.OP_READ);
}
}
public void stop() {
run = false;
selector.wakeup();
}
}
It seems the code works well, are there any more suggestions?? thx!
On 2=D4 19=C8=D5, =CF =CE=E73=CA=B113=B7=D6, EJP <esmond.not.p...@not.bi=
gpond.com> wrote:
lightning wrote:
It seems that udpchannel is always writable
Almost always, unless the socket send buffer is full. You shouldn't
normally register for OP_WRITE unless you've had a short write: in the
case of UPD, that would be a write() return of zero. If you get that,
queue the datagram, register for OP_WRITE, and when you get OP_WRITE,
unqueue the datagrams in the queue and try to send them all. If you
succeed, unregister OP_WRITE again.