• udp用户数据报协议


      UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17。

      UDP协议全称是用户数据报协议[1]  ,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。
     
      与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互连)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。
     
      选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和QQ就是使用的UDP协议。
     
      每个UDP报文分UDP报头和UDP数据区两部分。报头由四个16位长(4个域组成,其中每个域各占用2个字节)字段组成,分别说明该报文的源端口、目的端口、报文长度以及校验值。
     
    服务端
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    
    public class UdpServer {
        public static void main(String[] args)throws IOException{  
            String str_send = "Hello UDPclient";  
            byte[] buf = new byte[1024];  
            //服务端在3000端口监听接收到的数据  
            DatagramSocket ds = new DatagramSocket(3000);  
            //接收从客户端发送过来的数据  
            DatagramPacket dp_receive = new DatagramPacket(buf, 1024);  
            System.out.println("server is on,waiting for client to send data......");  
            boolean f = true;  
            while(f){  
                //服务器端接收来自客户端的数据  
                ds.receive(dp_receive);  
                System.out.println("server received data from client:");  
                String str_receive = new String(dp_receive.getData(),0,dp_receive.getLength()) +   
                        " from " + dp_receive.getAddress().getHostAddress() + ":" + dp_receive.getPort();  
                System.out.println(str_receive);  
                //数据发动到客户端的3000端口  
                DatagramPacket dp_send= new DatagramPacket(str_send.getBytes(),str_send.length(),dp_receive.getAddress(),9000);  
                ds.send(dp_send);  
                //由于dp_receive在接收了数据之后,其内部消息长度值会变为实际接收的消息的字节数,  
                //所以这里要将dp_receive的内部消息长度重新置为1024  
                dp_receive.setLength(1024);  
            }  
            ds.close();  
        }  
    }

    客户端

    import java.io.IOException;
    import java.io.InterruptedIOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    
    public class UdpClient {
        private static final int TIMEOUT = 5000;  //设置接收数据的超时时间  
        private static final int MAXNUM = 5;      //设置重发数据的最多次数  
        public static void main(String args[])throws IOException{  
            String str_send = "Hello UDPserver";  
            byte[] buf = new byte[1024];  
            //客户端在9000端口监听接收到的数据  
            DatagramSocket ds = new DatagramSocket(9000);  
            InetAddress loc = InetAddress.getLocalHost();  
            //定义用来发送数据的DatagramPacket实例  
            DatagramPacket dp_send= new DatagramPacket(str_send.getBytes(),str_send.length(),loc,3000);  
            //定义用来接收数据的DatagramPacket实例  
            DatagramPacket dp_receive = new DatagramPacket(buf, 1024);  
            //数据发向本地3000端口  
            ds.setSoTimeout(TIMEOUT);              //设置接收数据时阻塞的最长时间  
            int tries = 0;                         //重发数据的次数  
            boolean receivedResponse = false;     //是否接收到数据的标志位  
            //直到接收到数据,或者重发次数达到预定值,则退出循环  
            while(!receivedResponse && tries<MAXNUM){  
                //发送数据  
                ds.send(dp_send);  
                try{  
                    //接收从服务端发送回来的数据  
                    ds.receive(dp_receive);  
                    //如果接收到的数据不是来自目标地址,则抛出异常  
                    if(!dp_receive.getAddress().equals(loc)){  
                        throw new IOException("Received packet from an umknown source");  
                    }  
                    //如果接收到数据。则将receivedResponse标志位改为true,从而退出循环  
                    receivedResponse = true;  
                }catch(InterruptedIOException e){  
                    //如果接收数据时阻塞超时,重发并减少一次重发的次数  
                    tries += 1;  
                    System.out.println("Time out," + (MAXNUM - tries) + " more tries..." );  
                }  
            }  
            if(receivedResponse){  
                //如果收到数据,则打印出来  
                System.out.println("client received data from server:");  
                String str_receive = new String(dp_receive.getData(),0,dp_receive.getLength()) +   
                        " from " + dp_receive.getAddress().getHostAddress() + ":" + dp_receive.getPort();  
                System.out.println(str_receive);  
                //由于dp_receive在接收了数据之后,其内部消息长度值会变为实际接收的消息的字节数,  
                //所以这里要将dp_receive的内部消息长度重新置为1024  
                dp_receive.setLength(1024);     
            }else{  
                //如果重发MAXNUM次数据后,仍未获得服务器发送回来的数据,则打印如下信息  
                System.out.println("No response -- give up.");  
            }  
            ds.close();  
        }
    }
     
      
     
  • 相关阅读:
    scrapy框架(一)
    selenium爬取京东商品信息
    自动化测试工具selenium的使用
    xpath选择器的使用
    爬取网页数据实例
    爬虫实操
    爬虫之`beautifulsoup4`模块
    DNS学习笔记
    MongoDB集群部署
    MongoDB单机部署
  • 原文地址:https://www.cnblogs.com/cnsdhzzl/p/7345169.html
Copyright © 2020-2023  润新知