java UDP

udp协议的特点:
  1. 发送数据都是需要把数据封装到数据包中再发送 的,面向无连接。
  1. 数据包大小不能超过64kb。
  2. 因为udp协议是面向无连接的, 所以会出现数据包丢失的情况。
  3. 因为面向无连接,所以速度快。
  4. udp协议是不分客户端与服务端,只分发送端与接收端。
数据包在什么情况下会丢失呢:
  1. 带宽不足的时候。
  1. cpu处理能力不足 的时候。

1.第一个UDP小程序

发送端
public class Demo01Sender {

    public static void main(String[] args) throws IOException {
        //1.创建UDP服务(创建码头)
        DatagramSocket socket = new DatagramSocket();
        //2.准备数据,把数据封包(准备集装箱)
        String data = "爱你一万年";
        byte buf[] = data.getBytes(); 
        DatagramPacket packet = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),9090);
        /*
         参数解释:
         DatagramPacket(byte[] buf, int length, InetAddress address, int port)
         buf:发送数据的字节数组
         length:发送数据的字节数
         address:对方的ip地址
         port:绑定的端口号
         */
        
        //3.调用UDP服务发送数据(运货)
        socket.send(packet);
        //4.关闭资源(释放端口号,释放码头)
        socket.close();
    }

}
接收端
public class Demo01Receiver {

    public static void main(String[] args) throws IOException {
        //1.创建UDP服务(创建码头)
        DatagramSocket socket  = new DatagramSocket(9090);
        //2.准备一个空的数据包(一个空的集装箱)
        byte buf[] = new byte[1024];//如果发送过来的数据大于1024字节,那么将接收不完整
        DatagramPacket packet = new DatagramPacket(buf,buf.length);
        //第三步: 调用up的服务接受数据包, 数据其实是存入了字节数组中的。数据包是依赖于字节数据存储东西的。
        socket.receive(packet);  // receive()该方法是一个阻塞型的方法, 如果没有接受数据的时候,会一直等待下去。
        System.out.println(packet.getAddress().getHostAddress()+ "接收端接收到的数据:"+ new String(buf,0,packet.getLength()));  // getLength() 获取本次接收到的字节个数。
        // getAddress()  获取对方的IP地址对象 , 
        
        //第四步:关闭资源
        socket.close();
    
    }
}

2.给飞Q发送信息

feiQ聊天也是使用了udp协议通讯的。

需求: 给feiQ发送信息。

飞Q要处理的格式数据:

version:time :sender : ip: flag:content ;
版本号: 时间:发送人: IP地址 : 标识符(32): 真正的内容

任何的网络程序都有自己的加密方式,如果给网络程序发送信息的时候,如果不符合他所要的格式数据,那么就会当成垃圾数据丢弃。

在udp协议中有一个ip地址称作为广播IP地址, 广播IP主机号为255的。
给广播IP地址发送消息的时候,在同一个网络段的同学都可以接受到。
IP地址 = 网络号 + 主机号
192.168.1.255


public class FeiQDemo {
    
    public static void main(String[] args) throws IOException {
        //第一步: 建立udp的服务
        DatagramSocket socket = new DatagramSocket();
        
        //准备数据,把数据封装到数据包中
        String data = getData("hello FeiQ");
        byte[] buf = data.getBytes();
        DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.255"), 2425);
        
        //调用udp的服务,发送数据
        socket.send(packet);
        
        //关闭资源
        socket.close();
    }
    
    public static String getData(String data){
        StringBuilder sb = new StringBuilder();
        sb.append("1.0:");
        sb.append(System.currentTimeMillis()+":");
        sb.append("习总:");
        sb.append("192.168.1.47:");
        sb.append("32:");
        sb.append(data);
        
        return sb.toString();
    }
}

3.多人聊天程序

main函数,负责创建和开启发送消息/接收消息线程
public class ChatMain {

    public static void main(String[] args) {
        //创建了接收端与发送端的线程对象
        ChatReceiver receive = new ChatReceiver();
        ChatSender  sender = new ChatSender();
        //启动线程接收与发送数据
        receive.start();
        sender.start();
    }
}
发送端
public class ChatSender extends Thread {
    
    public void run() {
        //第一步: 建立udp的服务
        DatagramSocket socket = null;
        try {
            socket = new DatagramSocket();
            //第二步:准备数据, 把数据封装到数据包中发送。
            //数据是来自于键盘
            BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            DatagramPacket packet  = null; 
            while((line = keyReader.readLine())!=null){
                //键盘录入的数据已经封装到了数据包中了。
                packet = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.255"), 9090);
                //调用udp的服务发送数据
                socket.send(packet);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            //关闭资源
            socket.close();
        }
    }
}

我要说说上面那个循环输入:

BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));            
while(!(line = keyReader.readLine())!=null){
    System.out.println(line);
}

每次执行到keyReader.readLine()程序都会被阻塞等待用户输入,不过不管输入什么都不会返回null导致循环终止, 除非我们把循环条件改为(如下),那么我们输入null时,会终止;

BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));            
while(!(line = keyReader.readLine()).equals("null")){
    System.out.println(line);
}
接收端
//群聊的接收端
public class ChatReceiver extends Thread {

    @Override
    public void run() {
        //第一步: 建立dup的服务
        try {
            DatagramSocket socket = new DatagramSocket(9090);
            //第二步:准备空的数据包,接收数据
            byte[] buf = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            //调用udp的服务不断的接受数据包。
            while(true){
                socket.receive(packet);
                System.out.println(packet.getAddress().getHostAddress()+"说:"+ new String(buf,0,packet.getLength()));
            }
        }  catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}

4.模拟丢包

发送端
public class UDPSafeSender {
    
    public static void main(String[] args) throws Exception {
        //第一步: 建立udp的服务
        DatagramSocket socket = new DatagramSocket();
        //准备数据,把数据封装到数据包中发送
        DatagramPacket packet  = null;
        for(int i =  0;  i < 10 ; i++){
            String data = i+": aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            //把数据封装到数据包中发送
            packet = new DatagramPacket(data.getBytes(), data.getBytes().length, InetAddress.getLocalHost(), 9090);
            //把数据发送出去
            socket.send(packet);
        }
        //关闭资源
        socket.close();
    }
}

这里发送的数据要有一定的大小,否则即使接收端cpu处理能力不足,但是数据也会缓存到寄存器中(1kb)大小

接收端
public class UDPSafeReceive {

    public static void main(String[] args) throws Exception {      
        //建立udp的服务
        DatagramSocket socket = new DatagramSocket(9090);
        //准备空的数据包,用于存储数据
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        boolean  flag = true;
        while(flag){
            socket.receive(packet);
            Thread.sleep(10);  //模拟cpu处理能力不足
            System.out.println("接收到的数据:"+ new String(buf,0,packet.getLength()));
        }
        //关闭资源
        socket.close();

    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,501评论 11 349
  • 11.1 引言 UDP是一个简单的面向数据报的运输层协议:进程的每个输出操作都正好产生一个UDP数据报,并组装成一...
    张芳涛阅读 7,926评论 1 6
  • 重发消息有两个原因:①接收方未收到,此时重发是应该的。②接收方收到消息但是发回的应答包丢失了,此时重发消息则重复了...
    Spartacus2015阅读 4,979评论 1 1
  • 1.这篇文章不是本人原创的,只是个人为了对这部分知识做一个整理和系统的输出而编辑成的,在此郑重地向本文所引用文章的...
    SOMCENT阅读 14,492评论 6 174
  • 廖聪若溪 2017年10月11日 车子到处跑, 白天跑, 晚上跑。 不休息, 不停止。 ...
    zhiqinzhou阅读 3,060评论 0 0

友情链接更多精彩内容