UDP
将数据及源和目的封装成数据包中,不需要建立连接
每个数据报的大小限制在64k内
因无连接,是不可靠协议
不需要建立连接,速度快
步话器(对讲机)就是UDP传输。
1.面向无连接的,网络通讯有两端,你到底在不在不重要,我就是把这个数据打成包发出去,
你在 就收到了,你不在 就丢掉。
我在发数据之前,咱俩不需要先建立连接。发送之前要打包。
但是对方的地址和端口号要知道。
可对方这地址不一定存在,端口也不一定开着。
2.它发的包是有限制的,一次不超过64K,超过64K的数据分成多包发。
3.不可靠,我发个2兆的东西,它需要分成许多小包发,我刚开始还能发成功,后来对方断开了,我还在这发,这种情况有可能,数据就丢失了。
4.但是它也有好处,速度快。我不用先确认对方在不在,不重要。我直接到位,如果对方在的话直接就收到了,
这种方式在生活中常见吗?咱聊天就是UDP的,qq飞秋聊天,凌波桌面共享,网络视频会议都是UDP的。丢点数据不重要,为了求速度。
UDP传输 :
DatagramSocket 与 DatagramPacket
java.net
类 DatagramSocket
此类表示用来发送和接收数据报包的套接字(插座)。
这个套接字既能发送又能接收,两个通讯端点都得有这个。
用它建立端点。建立完之后,这个类有发送和接收的方法:
void | receive(DatagramPacket p) 从此套接字接收数据报包。 |
void | send(DatagramPacket p) 从此套接字发送数据报包。 |
发送什么东西得指定一下,UDP要把数据封装成包发送出去,所以它又给我们提供了数据包对象。
数据包中会封装什么呢?包里有饼干(数据实体)、盒子上贴有发送地址发送人和收货地址收货人(发送和接收两端的地址和端口号)。
java.net
类 DatagramPacket
public final class DatagramPacket
extends Object此类表示数据报包。
数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。
构造方法摘要 | |
---|---|
DatagramPacket(byte[] buf, int length) 构造 DatagramPacket ,用来接收长度为 length 的数据包。 | |
DatagramPacket(byte[] buf, int length,InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。 | |
DatagramPacket(byte[] buf, int offset, int length) 构造 DatagramPacket ,用来接收长度为 length 的包,在缓冲区中指定了偏移量。 | |
DatagramPacket(byte[] buf, int offset, int length,InetAddress address, int port) 构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。 | |
DatagramPacket(byte[] buf, int offset, int length,SocketAddress address) 构造数据报包,用来将长度为 length 偏移量为 offset 的包发送到指定主机上的指定端口号。 | |
DatagramPacket(byte[] buf, int length,SocketAddress address) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。 |
这么多构造函数,它们的功能不一样。
凡是参数中带地址和端口号的(InetAddress address, int port),都是用来构造发送数据包的。
玩socket主要记住流程,代码可以查文档。
流程:
1.建立发送端,接收端。
2.建立数据包。
3.调用Socket的发送接收方法。
4.关闭Socket。
发送端与接收端是两个独立的运行程序。
import java.net.*;
/*
需求:通过UDP传输方式,将一段文字数据发送出。
思路:
1.建立UDP的socket服务(建立端点)
2.提供数据,并将数据封装到数据包中。
3.通过socket服务的发送功能,将数据包发出去。
4.关闭资源。
*/
class UDPSend
{
public static void main(String[] args) throws Exception
{
//创建udp服务,通过DatagramSocket对象。
DatagramSocket ds = new DatagramSocket(8888);
//确定数据,并封装成数据包。DatagramPacket(byte[] buf, int length, InetAddress address, int port)
byte[] buf = "UDP socket shuju fasong wo lai la".getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10000);
//通过socket服务,将已有的数据包发出去
ds.send(dp);
//关闭资源
ds.close();
}
}
/*
需求:定义一个应用程序,用于接收UDP协议传输的数据并进行处理。
思路:
1.定义UDP的socket服务,建立端点。并定义监听端口。
2.定义一个数据包,因为要存储接收到的字节数据。
数据包中的内容很复杂,因为数据包对象中有更多功能可以提取字节数据中不同的数据信息。
3.通过socket服务的receive方法将收到的数据存入已定义好的数据包中。
4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。
5.关闭资源。
*/
class UDPReceive
{
public static void main(String[] args) throws Exception
{
//定义UDP的socket服务,建立端点。
DatagramSocket ds = new DatagramSocket(10000);
//定义一个数据包,用来存储接收到的字节数据。DatagramPacket(byte[] buf, int length)
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//通过socket的receive方法接收数据,并存储到定义好的包中
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();
}
}
键盘录入方式数据:
import java.net.*;
import java.io.*;
class UDPSend
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket(8889);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line=br.readLine())!=null)
{
if(line.equals("886"))
{
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.100"), 10001);
ds.send(dp);
}
ds.close();
}
}
class UDPReceive
{
public static void main(String[] args) throws Exception
{
DatagramSocket ds = new DatagramSocket(10001);
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String data = new String(dp.getData(), 0, dp.getLength());
System.out.println(ip+"::"+port+"\r\n"+data);
}
}
}
聊天:
import java.net.*;
import java.io.*;
class Send implements Runnable
{
private DatagramSocket ds;
Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line=br.readLine())!=null)
{
if(line.equals("886"))
{
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.100"), 10001);
ds.send(dp);
}
ds.close();
}
catch (Exception e)
{
throw new RuntimeException();
}
}
}
class Receive implements Runnable
{
private DatagramSocket ds;
Receive(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String data = new String(dp.getData(), 0, dp.getLength());
System.out.println(ip+"::"+port+"\r\n"+data);
}
}
catch (Exception e)
{
throw new RuntimeException();
}
}
}
class UDPDemo2
{
public static void main(String[] args)throws Exception
{
DatagramSocket ds = new DatagramSocket(8889);
Send s = new Send(ds);
Receive r = new Receive(ds);
Thread t1 = new Thread(s);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}
广播,群聊:“192.168.1.255”最后一个字节是255的是广播地址,给这个段的所有地址群发消息。
import java.net.*;
import java.io.*;
class Send implements Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line=br.readLine())!=null)
{
if(line.equals("886"))
{
break;
}
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.255"), 10002);
ds.send(dp);
}
ds.close();
}
catch (Exception e)
{
throw new RuntimeException("发送端失败");
}
}
}
class Receive implements Runnable
{
private DatagramSocket ds;
public Receive(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String data = new String(dp.getData(), 0, dp.getLength());
System.out.println(ip+"::"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失败");
}
}
}
class UDPDemo2
{
public static void main(String[] args)throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receiveSocket = new DatagramSocket(10002);
Send s = new Send(sendSocket);
Receive r = new Receive(receiveSocket);
Thread t1 = new Thread(s);
Thread t2 = new Thread(r);
t1.start();
t2.start();
}
}
简易界面版聊天工具:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
class QQDemo
{
public Frame f;
public Button headPhoto, sendButton;
public Dialog chatWindow;//Dialog(Frame owner, String title, boolean modal)
public TextArea readArea, writeArea;//TextArea(int rows, int columns)
QQDemo()
{
init();
}
public void init()
{
f = new Frame("my frame");
f.setBounds(900,10,250,600);
f.setLayout(new FlowLayout());
f.setFont(new Font("宋体",Font.PLAIN,30));
headPhoto = new Button("头像");
f.add(headPhoto);
chatWindow = new Dialog(f, "对话", false);
chatWindow.setBounds(400,200,600,600);
chatWindow.setLayout(new FlowLayout());
chatWindow.setFont(new Font("宋体",Font.PLAIN,20));//Font(String name, int style, int size)
Rectangle rec = chatWindow.getBounds();
readArea = new TextArea(10,50);
readArea.setEditable(false);
writeArea = new TextArea(10,50);
sendButton = new Button("发送");
chatWindow.add(readArea);
chatWindow.add(sendButton);
chatWindow.add(writeArea);
myEvent();
f.setVisible(true);
}
private void myEvent()
{
//关闭窗体
chatWindow.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
chatWindow.setVisible(false);
}
});
//聊天窗口关闭。
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
//弹出对话框。
headPhoto.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if(e.getClickCount()==2)
{
readArea.setText(null);
chatWindow.setVisible(true);
try
{
DatagramSocket receiveSocket = new DatagramSocket(10003);
Receive r = new Receive(receiveSocket);
Thread t2 = new Thread(r);
t2.start();
}
catch (Exception e1)
{
}
}
}
});
sendButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
DatagramSocket sendSocket = new DatagramSocket();
Send s = new Send(sendSocket);
Thread t1 = new Thread(s);
t1.start();
}
catch (Exception e1)
{
}
}
});
}
class Send implements Runnable
{
private DatagramSocket ds;
public Send(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
byte[] buf = writeArea.getText().getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.1.101"), 10003);
ds.send(dp);
readArea.append("\r\n"+InetAddress.getLocalHost().getHostAddress()+":\r\n"+new String(dp.getData(), 0, dp.getLength())+"\r\n");
writeArea.setText(null);
ds.close();
}
catch (Exception e)
{
throw new RuntimeException("发送端失败");
}
}
}
class Receive implements Runnable
{
private DatagramSocket ds;
public Receive(DatagramSocket ds)
{
this.ds = ds;
}
public void run()
{
try
{
while(true)
{
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
String data = new String(dp.getData(), 0, dp.getLength());
readArea.append("\r\n"+ip+":\r\n"+data+"\r\n");
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失败");
}
}
}
public static void main(String[] args)
{
new QQDemo();
}
}
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------