黑马程序员---UDP传输

UDP是一种无连接的传输协议,它将数据与源和目的地信息封装在数据包中,每个数据包大小限制在64KB,由于不建立连接,所以 UDP 提供的是不可靠的服务,但因此它具有更快的传输速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

 

UDP
      将数据及源和目的封装成数据包中,不需要建立连接
      每个数据报的大小限制在64k内
      因无连接,是不可靠协议
      不需要建立连接,速度快

步话器(对讲机)就是UDP传输。

1.面向无连接的,网络通讯有两端,你到底在不在不重要,我就是把这个数据打成包发出去,

你在 就收到了,你不在 就丢掉。

我在发数据之前,咱俩不需要先建立连接。发送之前要打包。

但是对方的地址和端口号要知道。

可对方这地址不一定存在,端口也不一定开着。

2.它发的包是有限制的,一次不超过64K,超过64K的数据分成多包发

3.不可靠,我发个2兆的东西,它需要分成许多小包发,我刚开始还能发成功,后来对方断开了,我还在这发,这种情况有可能,数据就丢失了。

4.但是它也有好处,速度快。我不用先确认对方在不在,不重要。我直接到位,如果对方在的话直接就收到了,

这种方式在生活中常见吗?咱聊天就是UDP的,qq飞秋聊天,凌波桌面共享,网络视频会议都是UDP的。丢点数据不重要,为了求速度。

 

UDP传输 :

DatagramSocket 与 DatagramPacket

java.net
DatagramSocket

此类表示用来发送和接收数据报包的套接字(插座)。

这个套接字既能发送又能接收,两个通讯端点都得有这个。

用它建立端点。建立完之后,这个类有发送和接收的方法:

 voidreceive(DatagramPacket p)
          从此套接字接收数据报包。
 voidsend(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培训、期待与您交流! ----------------------

详细请查看:http://edu.youkuaiyun.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值