【我的Java笔记】网络编程_UDP协议编程

UDP协议编程(接收端与发送端)

1.UDP协议原理图解:




2.UDP协议通讯的特点:

(1)之间无需建立连接通道(以数据包的形式发往目的地)

(2)属于不可靠协议

(3)无需建立连接通道,执行效率高

(4)发送数据大小有限


3.UDP程序操作步骤

(1)发送数据包:

①使用DatagramSocket() 创建一个数据包套接字

②使用DatagramPacket(byte[] bys,int offset,int length,InetAddress address,int port) 创建要返送的数据

③使用DatagramSocket类的send() 方法发送数据包

④关闭资源

(2)接受数据包:

①使用DatagramSocket(int port) 创建数据包套接字,绑定到指定的端口

②使用DatagramPacket(byte[] bys,int length) 创建字节数组来接受数据包(接收容器)

③使用DatagramPacket 类的receive() 方法接受UDP包

④解析数据包里面的内容,输出到控制台

⑤关闭资源


注:

(1)DatagramSocket 类的receive() 方法,如果还没有可以接受的数据,此方法会一直处于阻塞状态

(2)接收端不能多次运行,因为此端口号已经被占用了,不能再使用此端口号。否则会出现:BindException绑定异常(只用运行一次)





InetAddress

1.概述:此类表示互联网协议(IP)地址


注:此类没有构造方法。

如果一个类没有构造方法:则这个类里面的成员方法都是静态的,该类中的某些静态方法的返回值是该类本身


2.成员方法:

(1)public static InetAddress getByName(String host)在给定主机名的情况下确定主机的 IP 地址

注:此主机名可以是pc机器的计算机名称,也可以是IP地址的文本表现形式

(2)public String getHostName()获取此 IP 地址的主机名

注:如果此 InetAddress 是用主机名创建的,则记忆并返回主机名

(3)public String getHostAddress()返回 IP 地址字符串(以文本表现形式)





DatagramSocket

1.概述:此类用来表示发送和接受数据包的套接字


2.构造函数:

(1)DatagramSocket()  构造数据报套接字并将其绑定到本地主机上任何可用的端口

     (2)DatagramSocket(int port) 创建数据报套接字并将其绑定到本地主机上的指定端口

(3)DatagramSocket(int port,InetAddress addr) 创建数据报套接字,将其绑定到指定的本地地址


3.成员方法:

(1)public void receive(DatagramPacket p)从此套接字接受数据包

注:此方法在接收到数据包前一直相当于阻塞状态

(2)public void send(DatagramPacket p)从此套接字发送数据包





DatagramPacket

1.概述:此类表示数据包

2.构造函数:
(1)DatagramPacket(byte [] bys,int length) 构造DatagramPacket,用来接收长度为 length 的数据包
(2)DatagramPacket(byte[] bys,int length,InetAddress address,int port)
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号


3.成员方法:

(1)public InetAddress getAddress() 返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的


(2)public byte[]getData()返回数据缓冲区

(3)public intgetLength()返回将要发送或接收到的数据的长度







例1:

// 发送端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Send {

	public static void main(String[] args) throws IOException {
		// (1)创建发送端DatagramSocket对象
		DatagramSocket ds = new DatagramSocket();
		
		// 发送的数据
		String str = "我爱国际米兰";
		
		byte [] bys = str.getBytes();
		int len = bys.length;
		// 创建InetAddress对象,获取IP地址
		InetAddress address = InetAddress.getByName("192.168.1.108");
		// 指定端口号
		int port = 1234;
		
		// (2)创建传输数据包对象
		DatagramPacket dp = new DatagramPacket(bys,len,address,port);
		
		// (3)调用DatagramSocket类里的send() 方法发送数据包
		ds.send(dp);
		
		// (4)释放资源
		ds.close();
	}
}


// 接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Receive {

	public static void main(String[] args) throws IOException {
		// (1)创建接收端DatagramSocket对象,并加入端口号
		DatagramSocket ds = new DatagramSocket(1234);
		
		// (2)创建数据包对象
		byte [] bys = new byte [1024];		// 定义缓冲区
		DatagramPacket dp = new DatagramPacket(bys,bys.length);
		
		// (3)调用DatagramSocket中的receive() 方法
		ds.receive(dp);		// 阻塞式方法,在接收到数据前一直处于阻塞
		
		// (4)读取数据
		byte [] bys2 = dp.getData();	// 返回数据缓冲区
		int len = dp.getLength();		// 返回将要发送或接收到的数据的长度
		InetAddress address = dp.getAddress();	// 返回某台机器的IP地址
		String ip = address.getHostAddress();	// 得到IP地址的文本形式
		
		// 将字符串打印至控制台
		String str = new String(bys2,0,len);
		System.out.println(ip+":给你发送了:"+str);
	}
}

结果:









例2:UDP的优化

//发送端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Send {
	public static void main(String[] args) throws Exception {

		// (1)创建发送端DatagramSocket对象
		DatagramSocket ds = new DatagramSocket();

		// (2)创建数据报包
		byte[] bys = "我爱国际米兰".getBytes();
		DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("192.168.1.108"), 1234);

		// (3)将数据以数据报包的形式发出去
		ds.send(dp);

		// (4)关闭资源
		ds.close();
	}
}


// 接受端
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receive {

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

		// (1)创建接收端的DatagramSocket对象
		DatagramSocket ds = new DatagramSocket(1234);

		// (2)创建一个接收容器接收数据
		byte[] bys = new byte[1024];
		DatagramPacket dp = new DatagramPacket(bys, bys.length);

		// (3)接收数据
		ds.receive(dp);

		// (4)解析数据并显示在控制台
		String ip = dp.getAddress().getHostAddress();	// 获取ip地址的字符串表现形式
		// 获取缓存区中的实际数据
		byte[] bys2 = dp.getData();
		// 获取实际缓冲区数据的长度
		int len = dp.getLength();
		String str = new String(bys2, 0, len);

		// 输出在控制台
		System.out.println(ip + "发送的数据是:" + str);

		// 关闭资源
		ds.close();
	}
}







例3:发送端使用键盘不停地录入数据,接收端不停的接收

// 发送端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

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

		// 创建发送端的DatagramSocket对象
		DatagramSocket ds = new DatagramSocket();

		// 创建字符缓冲流读取键盘录入的数据
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		// 一次读取一行
		String line = null;
		while ((line = br.readLine()) != null) {
			// 自定义结束条件
			if ("再见".equals(line)) {
				break;
			}
			// 创建数据报包
			byte[] bys = line.getBytes();
			DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("192.168.1.108"), 1234);

			// 发送数据
			ds.send(dp);
		}

		// 释放资源
		ds.close();
	}
}


// 接收端
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

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

		// 创建接收端的Datagramsocket对象
		DatagramSocket ds = new DatagramSocket(1234);
		
		while (true) {

			byte[] bys = new byte[1024];
			DatagramPacket dp = new DatagramPacket(bys, bys.length);

			// 接收数据
			ds.receive(dp);

			// 获取ip字符串的表现形式
			String ip = dp.getAddress().getHostAddress();

			// 解析数据接收容器,获取里面实际的内容
			byte[] bys2 = dp.getData();
			int len = dp.getLength();		// 获取实际数据缓冲区实际长度
			String s = new String(bys2, 0, len);

			// 显示到控制台
			System.out.println("from" + ip + "data is :" + s);

		}

	}
}

结果:

发送端:



接收端:










例4:使用多线程方法实现UDP协议编程(让发送端和接收端位于一个窗口下main)

// 测试类
import java.net.DatagramSocket;
import java.net.SocketException;

public class Test {
	public static void main(String[] args) {

		try {
			
			// 创建发送端和接收端的Socket对象
			DatagramSocket sendSocket = new DatagramSocket();
			DatagramSocket receiveSocket = new DatagramSocket(1234);

			// 分别创建资源对象
			SendThread st = new SendThread(sendSocket);
			ReceiveThread rt = new ReceiveThread(receiveSocket);

			// 创建线程类对象
			Thread t1 = new Thread(st);
			Thread t2 = new Thread(rt);

			// 启动线程
			t1.start();
			t2.start();

		} catch (SocketException e) {
			e.printStackTrace();
		}
	}
}


// 发送端线程
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendThread implements Runnable {
	// 定义一个变量
	private DatagramSocket ds;

	public SendThread(DatagramSocket ds) {
		this.ds = ds;
	}

	@Override
	public void run() {
		try {
		
			// 以标准IO流的方式读取键盘录入的数据
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			String line = null;
			while ((line = br.readLine()) != null) {
				// 自定义结束条件
				if ("over".equals(line)) {
					break;
				}
				// 创建数据报包
				byte[] bys = line.getBytes();
				DatagramPacket dp = new DatagramPacket(bys, bys.length, InetAddress.getByName("192.168.1.108"), 1234);

				// 发送数据
				ds.send(dp);

			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			if (ds != null) {
				ds.close();
			}
		}

	}

}


// 接收端线程
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ReceiveThread implements Runnable {
	// 定义一个变量
	private DatagramSocket ds;

	public ReceiveThread(DatagramSocket ds) {
		this.ds = ds;
	}

	@Override
	public void run() {
		try {
			while (true) {
				// 创建数据缓冲区
				byte[] bys = new byte[1024];
				DatagramPacket dp = new DatagramPacket(bys, bys.length);

				// 接收数据
				ds.receive(dp);

				// 获取ip字符串的表现形式
				String ip = dp.getAddress().getHostAddress();

				// 解析数据接收容器,获取里面实际的内容
				byte[] bys2 = dp.getData();
				int len = dp.getLength();		// 获取实际数据缓冲区实际长度
				String str = new String(bys2, 0, len);

				// 显示到控制台
				System.out.println("from" + ip + "data is :" + str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}


结果:
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值