网络编程之UDP

来源:互联网 发布:开源网络监控工具 编辑:程序博客网 时间:2024/05/02 01:23


UDP 是User Datagram Protocol的简称, 中文名是用户数据包协议,是 OSI 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。


UDP连接编程特点:

UDP 将数据及源和目的封装在数据包中,不需要建立连接,

每个数据包的大小限制在64K

因无连接,是不可靠协议

不需要建立连接,速度快

 聊天、网络视频会议、桌面共享 多用UDP

UDP建立连接的类是DatagramSocket  

   发送和接收都需要先建立连接端,也叫做数据报套接字,通过DatagramSocket的实例化来实现,其中接收端在实例化端的时候需要指定一个侦听端口号,这个端口号必须和发送端的数据报包中封装的端口一致,而发送端也可以指定发送端口号,但是因为不是建立通信必须的,所以通常由系统自动分配。

   数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。

    在 DatagramSocket 上总是启用 UDP 广播发送。为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。 

     例如:

       DatagramSocket us=new DatagramSocket(null);  //发送端

       DatagramSocket ur=new DatagramSocket(8000);//接收端

数据报包:DatagramPacket  实现无连接的包投递服务

     数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。 通过数据报包,我们可以非常方便的包装

UDP实现通信的三个要素:

IP地址 ,端口号, 数据;

      数据报包类包含了多个构造方法,其中最为常用的两个是:

DatagramPacket(byte[] buf, int length)
构造 DatagramPacket,用来接收长度为 length 的数据包。          //接收端用,将接收到的数据包装到指定数组中以便后面的操作(后面的操作首先就是等待DatagramSocket对象调用receive方法,将接收缓冲区的数据接收到指定数据中,然后从该数组中提取相应的数据);DatagramPacket(byte[] buf, int length,InetAddress address, int port)
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。          //发送端用,用于将接收端的IP地址,端口号,以及包含了需要发送数据的数组进行包装,备用(等待DatagramSocket对象调用SEND方法,

             

       下面是分别建立的两个类,发送端实现固定发送一段文字,接收端实现接收指定端口上发来的数据,并提取发送端的IP地址和发送的数据显示在控制台上


     发送端

package com.io;

import java.io.IOException;

import java.net.*;

public class UDPdemoTrans {

public static void main(String[] args) throws IOException {

DatagramSocket dsk=new DatagramSocket();

byte []data="udp is coming".getBytes();

DatagramPacket dgp=new DatagramPacket(data,data.length,InetAddress.getByName("127.0.0.1"),8000);

dsk.send(dgp);

dsk.close();

}}


接收端

package com.io;

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;


public class UDPdemoReceive{

public static void main(String[]args) throws IOException{

DatagramSocket ds=new DatagramSocket(8000);

byte []buf=new byte [1024];

DatagramPacket dp=new DatagramPacket(buf,buf.length);

ds.receive(dp);

//通过数据包的方法获取其中的数据

String ip=dp.getAddress().getHostAddress();

String data=new String(dp.getData(),0,dp.getLength());

int port=dp.getPort();

System.out.println(ip+"::"+data+"::"+port);

ds.close();

}}

       

                            小结示例:编写一个聊天程序,通过多线程技术实现,有收数据和发数据两个部分,这两部分需要同时执行,一个线程控制收,一个线程控制发送;

                                    分析: 因为收发并不是同时发生,所以需要定义两个run方法,有两种方式可以实现多线程,一种是继承tread类,还有就是实现runanable方法,当只需要使用run方法的时候,显然实现接口更方便,为了逻辑清楚,把这两个run方法要封装到不同的类中。

package com.io;

import java.net.*;

import java.io.*;

public class UDPrun {

/**

 * @param args

 * @throws SocketException 

 */

启动类:

public static void main(String[] args) throws SocketException {

// TODO Auto-generated method stub

DatagramSocket us=new DatagramSocket();

      DatagramSocket ur=new DatagramSocket(8000);

new Thread(new UDPsend(us)).start();

new Thread(new UDPreceive(ur)).start();

}

}


发送端

 

 class UDPsend implements Runnable{
public  DatagramSocket dss;
public UDPsend( DatagramSocket dss) {
this.dss = dss;
}
public void run(){
try {
 //  DatagramSocket us=new DatagramSocket();
BufferedReader bfr=new BufferedReader(new InputStreamReader(System.in));
byte[] buf=null;
String bufs=null;
while(true){
bufs = bfr.readLine();
buf=bufs.getBytes();
if("over".equals(bufs))break;else{
DatagramPacket dsp=new DatagramPacket(buf, buf.length, InetAddress.getByName("127.0.0.1"),8000);
  
dss.send(dsp);

}
}
} catch (Exception e) {
}   
}
}



      接收端


class UDPreceive implements Runnable{
    public  DatagramSocket ur;
public UDPreceive(DatagramSocket ur) {
this.ur=ur;
}

public void run(){
byte[]bufr=new byte[1024];
DatagramPacket dsr=new DatagramPacket(bufr, bufr.length);
try {
while(true){
ur.receive(dsr);
String ip=dsr.getAddress().getHostAddress();//获取主机IP地址
   String data=new String(dsr.getData()); //将接收到的数组数据封装成字符串
int p=dsr.getPort(); //获取发送端口号
System.out.println(ip+":"+data+":"+p);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

原创粉丝点击