计算机基础-编程语言 JavaSE基础笔记 Java网络编程(2)

UDP相关类

UDP是基于数据报的传输协议,java.net.DatagramSocket类负责接收和发送UDP数据报,java.net.DatagramPacket表示UDP数据报。

(1)DatagramSocket类

每个DatagramSocket与一个数据报套接字(内含本地主机的IP和端口)绑定,每个DatagramSocket可以把UDP数据报发往任意一个远程DatagramSocket,也可接收来自任何远程DatagramSocket的数据报。在UDP数据报中包含了目的地址信息,DatagramSocket可根据该信息把数据报发往目的地。在上节讲的TCP通信中,客户端Socket必须先与服务器端建立连接,连接建好后,服务器端也会持有与客户端相连的Socket,且双方的Socket是对应的,共同构成了两个端点之间的虚拟通信链路。而UDP是无连接的协议,客户端DatagramSocket与服务器端DatagramSocket不存在对应关系,两者无须建立连接就能交换数据。每个DatagramSocket对象都会与一个本地端口绑定,在此端口监听发送过来的数据报。在服务器程序中,由程序显式地为DatagramSocket指定端口;而在客户程序中,一般由操作系统为DatagramSocket分配本地端口,这种端口也称为匿名端口。

DatagramSocket有如下一些构造方法。

DatagramSocket类的常用方法

方    法

功    能

void send(DatagramPacket p) throws IOException

发送一个UDP数据报,即一个DatagramPacket对象

void receive(DatagramPacket p) throws IOException

接收一个UDP数据报,即一个DatagramPacket对象

void connect(InetAddress address, int port)

将该UDPSocket变成一个连接型的UDPSocket

void disconnect()

将该UDPSocket变成一个非连接型的UDPSocket

void close()

关闭UDPSocket

(2)DatagramPacket类

DatagramPacket类的对象代表一个UDP数据报。用UDP发送数据时,先要根据发送的数据生成一个DatagramPacket对象,然后通过它的send()方法发送这个对象;接收时也先要根据要接收数据的缓冲区生成一个DatagramPacket对象,然后通过它的receive()方法接收这个对象的数据内容。 DatagramPacket类的构造方法分为两类:一类创建的对象用来接收数据报;另一类创建的对象则用来发送数据报。它们的区别是,用于发送数据报的构造方法需要设定数据报到达的目的地址(若是“连接型”UDP,则不需要设定这个地址),而用于接收数据报的构造方法无须设定地址。

用于接收数据报的构造方法如下。 

DatagramPacket(byte[] buf, int length) 功能:由接收缓冲区(byte[]字节数组与它的长度length)生成一个DatagramPacket对象。buf表示保存传入数据报的缓冲区,length表示要读取的字节数。

DatagramPacket(byte[] buf, int offset, int length) 功能:构造DatagramPacket,用来接收长度为length的包,在缓冲区中指定了偏移量。

用于发送数据报的构造方法如下

DatagramPacket(byte[] buf, int length, InetAddress address, int port) 功能:构造数据报,用来将长度为length的包发送到指定主机上的指定端口。length参数必须小于等于buf.length。因为默认UDPSocket是非连接型,故要在每一个发送用的UDP数据报中携带接收方的IP和端口号。

DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) 功能:构造数据报,用来将长度为length、偏移量为offset的包发送到指定主机上的指定端口,length参数必须小于等于buf.length。

DatagramPacket类的常用方法

方    法

功    能

byte[] getData()

返回DatagramPacket对象中包含的数据

int getLength()

返回发送/接收数据的长度

int getOffset()

返回发送/接收数据在byte[]中的偏移

InetAddress getAddress()

返回对方的IP地址,用InetAddress对象表示

int getPort()

返回对方的端口号

void setData(byte[] buf,int offset,int length)

设置该DatagramPacket对象中包含的数据

void setAddress(InetAddress iaddr)

设置该DatagramPacket对象中包含的IP地址

void setPort(int iport)

设置该DatagramPacket对象中包含的端口号

举例:UDP通信程序

【例14.3】一个简单UDP通信程序,客户程序向服务器程序发送任意的字符串,服务器端收到后,计算字符串的长度并向客户端回送相同的字符串。

(1)首先建立一个UDP服务器程序。在程序中创建了一个在9777端口上等待接收数据报的DatagramSocket对象。当有数据报要接收时,创建一个DatagramPacket对象接收此数据报。收到后分析数据报,并再次创建一个DatagramPacket对象回送此数据报。

(2)客户端程序创建一个DatagramSocket对象准备发送数据。该对象把要发送的数据打包成一个数据包,并在包中写明要发送给远程服务器的IP地址与端口号。

运行上面的两个程序,客户程序向服务器程序发送数据包,服务器接收此包,显示收到的字符串内容以及客户机的IP地址和端口号

服务端代码:

 客户端部分:

 运行结果:

源代码部分:

服务器端

package org;
	import java.io.*;
	import java.net.*;
	import java.awt.*;
	import java.awt.event.*;
	public class UDPServer {
		public static void main(String[] args) throws Exception {
			DatagramSocket ds = new DatagramSocket(9777);		// 在9777端口上创建UDPSocket
			Frame f = new Frame("UDPServer");
			f.setLocation(400, 300);
			f.setSize(300, 300);
			TextField tf = new TextField(40);
			TextArea list = new TextArea();
			f.add(list, BorderLayout.NORTH);
			f.pack();
			f.setVisible(true);
			f.addWindowListener(new WindowAdapter() {		// 关闭窗口
				public void windowClosing(WindowEvent e) {
					System.exit(0);
				}
			});
			byte[] buf = new byte[1024];						// 接收缓冲区
			DatagramPacket dp = null; 						// 接收UDP数据包
			DatagramPacket sdp = null; 						// 发送UDP数据包
			boolean more = true; 							// 控制UDP服务器
			while (more) {
				dp = new DatagramPacket(buf, 1024); 			// 创建一个用于接收的UDP数据包
				ds.receive(dp); 							// 等待任一个客户机发数据包
				InetAddress caddr = dp.getAddress(); 			// 获取客户机的IP地址
				int cport = dp.getPort();			 		// 获取客户机的端口号
				// 获取客户机发送的文本内容
				String s = new String(dp.getData(), dp.getOffset(), dp.getLength());
				String str = "客户机 IP: " + caddr + " 客户机端口号:" + cport+ "\n"
						+ "  客户机发送的数据是:" + s + " \n";
				list.append(str);
				String rs = new String("字符串:" + s + " 的长度是:" + s.length());
				byte[] sbuf = rs.getBytes();					// 将串转换成字节数组
				// 生成一个发送回特定客户机的UDP数据包的DatagramPacket对象
				sdp = new DatagramPacket(sbuf, sbuf.length, caddr, cport);
				ds.send(sdp); 							// 向客户机发回响应信息
			}
		}
	}

 客户端:

package org;
	import java.io.*;
	import java.net.*;
	import java.util.Date;
	import java.awt.*;
	import java.awt.event.*;
	public class UDPClient {
		static List list = new List(6);
		static TextField tf = new TextField(40);
		static DatagramPacket sdp = null;
		static DatagramPacket rdp = null;
		public static void main(String[] args) throws Exception {
			Frame f = new Frame("UDPClient");
			DatagramSocket ds = new DatagramSocket();		// 生成一个客户机用UDPSocket
			f.setLocation(400, 300);
			f.setSize(300, 300);
			f.add(tf, BorderLayout.SOUTH);
			f.add(list, BorderLayout.NORTH);
			f.pack();
			f.addWindowListener(new WindowAdapter() {			// 关闭窗口
				public void windowClosing(WindowEvent arg0) {
					System.exit(0);
				}
			});
			tf.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e) {
					try {
						byte[] rbuf = new byte[1024], 			// 接收缓冲区大小设置为1024
						sbuf = null;
						String str =tf.getText();				// 获取文本框的内容
						list.add(str);						// 将数据添加到列表框中
						tf.setText(null);
						sbuf = str.getBytes(); 					// 转换字节数组
						// 生成一个发送给UDP服务器的UDP数据包
						sdp = new DatagramPacket(sbuf,
 							sbuf.length, InetAddress.getByName("127.0.0.1"), 9777);
						// 生成一个发送给UDP服务器的UDP数据包 
						DatagramSocket ds = new DatagramSocket(); 
						ds.send(sdp); 						// 发送出去
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
			});
			f.setVisible(true);
			ds.close(); 											// 关闭Socket
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simon_Smith

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值