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();

    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容

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