UDP/TCP 協議

UDP: User Datagram Protocol  用戶數據報協議 是一種無連接的協議。UDP有不提供數據包分組、組裝和不能對數據包進行排序的缺點,也就是說,當報文發送之後,是無法得知其是否安全完整到達的。UDP用來支持那些需要在計算機之間傳輸數據的網絡應用。包括網絡視頻會議系統在內的衆多的客戶/服務器模式的網絡應用都需要使用UDP協議。

使用UDP: 在選擇使用協議的時候,選擇UDP必須要謹慎。在網絡質量令人十分不滿意的環境下,UDP協議數據包丟失會比較嚴重。但是由於UDP的特性:它不屬於連接型協議,因而具有資源消耗小,處理速度快的優點,所以通常音頻、視頻和普通數據在傳送時使用UDP較多


UDP廣播:廣播使用廣播地址255.255.255.255,將消息發送到在同一廣播網絡上的每個主機。值得強調的是:本地廣播信息是不會被路由器轉發。當然這是十分容易理解的,因爲如果路由器轉發了廣播信息,那麼勢必會引起網絡癱瘓。這也是爲什麼IP協議的設計者故意沒有定義互聯網範圍的廣播機制。其實廣播顧名思義,就是想局域網內所有的人說話,但是廣播還是要指明接收者的端口號的,因爲不可能接受者的所有端口都來收聽廣播。

發送接收 demo:

    public static void sendBroadcast(byte[] data, int port) throws Exception{
        DatagramSocket socket = new DatagramSocket();
        socket.setBroadcast(true);
        DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("255.255.255.255"), port);
        socket.send(packet);
    }

    public static void receiveBoradcast(int port) {
        new Thread(new Runnable() {

            DatagramSocket socket;

            @Override
            public void run() {
                while (true) {
                    try {
                        receive(port);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            public void receive(int port) throws Exception{
                if (socket == null || socket.isClosed()) {
                    socket = new DatagramSocket(port);
                    socket.setBroadcast(true);
                }

                byte[] buffer = new byte[1024 * 100];
                DatagramPacket packet = new DatagramPacket(buffer , buffer.length);
                socket.receive(packet);
                String data = new String(packet.getData(), 0, packet.getLength());
                Log.i("receiver", data);
                socket.close();
            }

        }).start();
    }


Netty 實現 demo

public class Broadcast {

    Channel udpChannel;

    public void send(String data) throws Exception{
        if(udpChannel != null) {
            udpChannel.writeAndFlush(data);
        }
    }

    public void init(int port) {
        NioEventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioDatagramChannel.class)
                .option(ChannelOption.SO_BROADCAST, true)
                .handler(new MessageToMessageEncoder<String>() {
                    @Override
                    protected void encode(ChannelHandlerContext ctx, String msg, List<Object> out) throws Exception {
                        InetSocketAddress remoteAddress = new InetSocketAddress("255.255.255.255", port);
                        out.add(new DatagramPacket(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8), remoteAddress));
                    }
                });
        udpChannel = bootstrap.bind(0).syncUninterruptibly().channel();
    }

}

public class BroadcastReceiver {

    public void start(int port){
        Bootstrap b = new Bootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            b.group(group)
                    .channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST, true)
                    .handler(new SimpleChannelInboundHandler<DatagramPacket>() {

                        @Override
                        protected void messageReceived(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
                            String req = packet.content().toString(CharsetUtil.UTF_8);
                            System.out.println(req);
                        }
                    });
            b.bind(port).sync().channel().closeFuture().await();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            group.shutdownGracefully();
        }
    }

}

多播  

多播數據報套接字類用於發送和接收 IP 多播包。MulticastSocket 是一種 (UDP) DatagramSocket,它具有加入 Internet 上其他多播主機的“組”的附加功能。

多播組通過 D 類 IP 地址和標準 UDP 端口號指定。D 類 IP 地址在 224.0.0.0 和 239.255.255.255 的範圍內(包括兩者)。地址 224.0.0.0 被保留,不應使用。

多播 demo

public class MultiBroadcast {

    public void startReveive(String host, int port) {

        new Thread(new Runnable() {

            MulticastSocket ms;

            private void receive(String host, int port) throws Exception{
                byte[] buf = new byte[1024 * 100];
                if(ms == null || ms.isClosed()) {
                    ms = new MulticastSocket(port);
                    DatagramPacket dp = new DatagramPacket(buf, buf.length);
                    InetAddress group = InetAddress.getByName(host);
                    ms.joinGroup(group);
                    ms.receive(dp);
                }

                Log.i("receiver", new String(buf));
                ms.close();
            }

            @Override
            public void run() {
                while (true) {
                    try {
                        receive(host, port);
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    public void send(String host, int port, String message) throws Exception{
        InetAddress group = InetAddress.getByName(host);
        MulticastSocket s = new MulticastSocket();
        s.joinGroup(group);
        DatagramPacket dp = new DatagramPacket(message.getBytes(),message.length(), group,port);
        s.send(dp);
        s.close();
    }

}

單播

public class UnicastBroadcast {

    public void send(String host, int port, byte[] message) throws Exception{
        //sending data to host and its port
        InetAddress address = InetAddress.getByName(host);
        // Initialize a datagram packet with data and address
        DatagramPacket packet = new DatagramPacket(message, message.length, address, port);
        // Create a datagram socket, send the packet through it, close it.
        DatagramSocket dsocket = new DatagramSocket();
        dsocket.send(packet);
        dsocket.close();
    }

    public void startReceive() {
        new Thread(new Runnable() {

            DatagramSocket dsocket;

            @Override
            public void run() {

            }

            private void receive(int port) throws Exception{

                byte[] buffer = new byte[2048];
                if(dsocket == null || dsocket.isClosed()) {
                    //receiving data from its port
                    dsocket = new DatagramSocket(port);
                    // Create a buffer to read datagrams into. If a
                    // packet is larger than this buffer, the
                    // excess will simply be discarded!

                    // Create a packet to receive data into the buffer
                    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

                    // Wait to receive a datagram
                    dsocket.receive(packet);
                    // Convert the contents to a string, and display them
                    String msg = new String(buffer);
                    System.out.println(packet.getAddress().getHostName() + ": " + msg);
                }
                
                dsocket.close();

            }

        }).start();
    }

}



Netty dmo

http://colobu.com/2014/10/21/udp-and-unicast-multicast-broadcast-anycast/#單播





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章