udp_nio.java.txt

来自「JGRoups源码」· 文本 代码 · 共 1,513 行 · 第 1/4 页

TXT
1,513 行
字号
        /** Vector<Connector>. A list of Connectors, one for each interface we listen on */        Vector connectors=new Vector();        boolean running=false;        static final Log mylog=LogFactory.getLog(ConnectorTable.class);        static final boolean mywarn=mylog.isWarnEnabled();        public ConnectorTable(InetSocketAddress mcast_addr,                              int receive_buffer_size, int receive_sock_buf_size,                              boolean ip_mcast, Receiver receiver) throws IOException {            this.receiver=receiver;            this.mcastAddr=mcast_addr;            this.receive_buffer=new byte[receive_buffer_size];            if(ip_mcast) {                mcast_sock=new MulticastSocket(mcast_addr.getPort());                // changed Bela Dec 31 2003: if loopback is disabled other members on the same machine won't be able                // to receive our multicasts                // mcast_sock.setLoopbackMode(true); // do not get own multicasts                mcast_sock.setReceiveBufferSize(receive_sock_buf_size);            }        }        public Receiver getReceiver() {            return receiver;        }        public void setReceiver(Receiver receiver) {            this.receiver=receiver;        }        /** Get all interfaces, create one Connector per interface and call start() on it */        public void start() throws Exception {            Connector tmp;            if(running)                return;            if(mcast_sock != null) {                // Start the thread servicing the incoming multicasts                t=new Thread(this, "ConnectorTable thread");                t.setDaemon(true);                t.start();            }            // Start all Connectors            for(Iterator it=connectors.iterator(); it.hasNext();) {                tmp=(Connector)it.next();                tmp.start();            }            running=true;        }        public void stop() {            Connector tmp;            for(Iterator it=connectors.iterator(); it.hasNext();) {                tmp=(Connector)it.next();                tmp.stop();            }            connectors.clear();            t=null;            if(mcast_sock != null) {                mcast_sock.close();                mcast_sock=null;            }            running=false;        }        public void run() {            // receive mcast packets on any interface of the list of interfaces we're listening on            DatagramPacket p=new DatagramPacket(receive_buffer, receive_buffer.length);            while(t != null && mcast_sock != null && !mcast_sock.isClosed()) {                p.setData(receive_buffer, 0, receive_buffer.length);                try {                    receivePacket(p, mcast_sock, this);                }                catch(Throwable th) {                    if(th == null || mcast_sock == null || mcast_sock.isClosed())                        break;                    if(mylog.isErrorEnabled()) mylog.error("exception=" + th);                    Util.sleep(300); // so we don't get into 100% cpu spinning (should NEVER happen !)                }            }            t=null;        }        /**         * Returns a list of local addresses (one for each Connector)         * @return List<SocketAddress>         */        public List getConnectorAddresses() {            Connector c;            ArrayList ret=new ArrayList();            for(Iterator it=connectors.iterator(); it.hasNext();) {                c=(Connector)it.next();                ret.add(c.getLocalAddress());            }            return ret;        }        /** Sends a packet. If the destination is a multicast address, call send() on all connectors.         * If destination is not null, send the message using <em>any</em> Connector: if we send a unicast         * message, it doesn't matter to which interface we are bound; the kernel will choose the correct         * interface based on the destination and the routing table. Note that the receiver will have the         * interface which was chosen by the kernel to send the message as the receiver's address, so the         * correct Connector will receive a possible response.         * @param msg         * @throws Exception         */        public void send(DatagramPacket msg) throws Exception {            InetAddress dest;            if(msg == null)                return;            dest=msg.getAddress();            if(dest == null)                throw new IOException("UDP_NIO.ConnectorTable.send(): destination address is null");            if(dest.isMulticastAddress()) {                // send to all Connectors                for(int i=0; i < connectors.size(); i++) {                    ((Connector)connectors.get(i)).send(msg);                }            }            else {                // send to a random connector                Connector c=pickRandomConnector(connectors);                c.send(msg);            }        }        private Connector pickRandomConnector(Vector conns) {            int size=conns.size();            int index=((int)(Util.random(size))) -1;            return (Connector)conns.get(index);        }        /**         * Adds the given interface address to the list of interfaces on which the receiver mcast         * socket has to listen.         * Also creates a new Connector. Calling this method twice on the same interface will throw an exception         * @param bind_interface         * @param local_port         * @param port_range         * @param receive_buffer_size         * @throws IOException         */        public void listenOn(String bind_interface, int local_port, int port_range,                              int receive_buffer_size, int receiver_sock_buf_size, int send_sock_buf_size,                             int ip_ttl, Receiver receiver) throws IOException {            if(bind_interface == null)                return;            NetworkInterface ni=NetworkInterface.getByInetAddress(InetAddress.getByName(bind_interface));            if(ni == null)                throw new IOException("UDP_NIO.ConnectorTable.listenOn(): bind interface for " +                        bind_interface + " not found");            Connector tmp=findConnector(ni);            if(tmp != null) {                if(mywarn) mylog.warn("connector for interface " + bind_interface +                        " is already present (will be skipped): " + tmp);                return;            }            // 1. join the group on this interface            if(mcast_sock != null) {                mcast_sock.joinGroup(mcastAddr, ni);                    if(mylog.isInfoEnabled()) mylog.info("joining " + mcastAddr + " on interface " + ni);            }            // 2. create a new Connector            tmp=new Connector(ni, local_port, port_range, receive_buffer_size, receiver_sock_buf_size,                    send_sock_buf_size, ip_ttl, receiver);            connectors.add(tmp);        }        private Connector findConnector(NetworkInterface ni) {            for(int i=0; i < connectors.size(); i++) {                Connector c=(Connector)connectors.elementAt(i);                if(c.getBindInterface().equals(ni))                    return c;            }            return null;        }        public void receive(DatagramPacket packet) {            if(receiver != null) {                receiver.receive(packet);            }        }        public String toString() {            StringBuffer sb=new StringBuffer();            sb.append("*** todo: implement ***");            return sb.toString();        }        public static void receivePacket(DatagramPacket packet, DatagramSocket sock, Receiver receiver) throws IOException {            int len;            sock.receive(packet);            len=packet.getLength();            if(len == 1 && packet.getData()[0] == 0) {                if(mylog.isTraceEnabled()) mylog.trace("received dummy packet");                return;            }            if(receiver != null)                receiver.receive(packet);        }    }    public static class MyReceiver implements Receiver {        ConnectorTable t=null;        public MyReceiver() {        }        public void setConnectorTable(ConnectorTable t) {            this.t=t;        }        public void receive(DatagramPacket packet) {            System.out.println("-- received " + packet.getLength() + " bytes from " + packet.getSocketAddress());            InetAddress sender=packet.getAddress();            byte[] buf=packet.getData();            int len=packet.getLength();            String tmp=new String(buf, 0, len);            if(len > 4) {                if(tmp.startsWith("rsp:")) {                    System.out.println("-- received respose: \"" + tmp + '\"');                    return;                }            }            byte[] rsp_buf=("rsp: this is a response to " + tmp).getBytes();            DatagramPacket response=new DatagramPacket(rsp_buf, rsp_buf.length, sender, packet.getPort());            try {                t.send(response);            }            catch(Exception e) {                e.printStackTrace();                System.err.println("MyReceiver: problem sending response to " + sender);            }        }    }    public static class MulticastReceiver implements Runnable {        Unmarshaller m=null;        DatagramSocket sock=null; // may be DatagramSocket or MulticastSocket        public void run() {            // receives packet from socket            // calls Unmarshaller.receive()        }    }    public static class Unmarshaller {        Queue q=null;        void receive(byte[] data, SocketAddress sender) {            // if (q) --> q.add()            // unserialize and call handleMessage()        }    }    static void help() {        System.out.println("UDP_NIO [-help] [-bind_addrs <list of interfaces>]");    }    public static void main(String[] args) {        MyReceiver        r=new MyReceiver();        ConnectorTable    ct;        String            line;        InetSocketAddress mcast_addr;        BufferedReader    in=null;        DatagramPacket    packet;        byte[]            send_buf;        int               receive_buffer_size=65000;        boolean           ip_mcast=true;        try {            mcast_addr=new InetSocketAddress("230.1.2.3", 7500);            ct=new ConnectorTable(mcast_addr, receive_buffer_size, 120000, ip_mcast, r);            r.setConnectorTable(ct);        }        catch(Throwable t) {            t.printStackTrace();            return;        }        for(int i=0; i < args.length; i++) {            if("-help".equals(args[i])) {                help();                continue;            }            if("-bind_addrs".equals(args[i])) {                while(++i < args.length && !args[i].trim().startsWith("-")) {                    try {                        ct.listenOn(args[i], 0, 1, receive_buffer_size, 120000, 12000, 32, r);                    }                    catch(IOException e) {                        e.printStackTrace();                        return;                    }                }            }        }        try {            ct.start(); // starts all Connectors in turn            in=new BufferedReader(new InputStreamReader(System.in));            while(true) {                System.out.print("> "); System.out.flush();                line=in.readLine();                if(line.startsWith("quit") || line.startsWith("exit"))                    break;                send_buf=line.getBytes();                packet=new DatagramPacket(send_buf, send_buf.length, mcast_addr);                ct.send(packet);            }        }        catch(Exception e) {            e.printStackTrace();        }        finally {            if(ct != null)                ct.stop();        }    }}interface Receiver {    /** Called when data has been received on a socket. When the callback returns, the buffer will be     * reused: therefore, if <code>buf</code> must be processed on a separate thread, it needs to be copied.     * This method might be called concurrently by multiple threads, so it has to be reentrant     * @param packet     */    void receive(DatagramPacket packet);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?