Java Socket-03 Java UDP Socket

    UDP 协议提供了一种不同于 TCP 协议的端到端服务。实际上 UDP 协议只实现两个功能: 1 )在 IP 协议的基础上添加了另一层地址(端口), 2 ) 对数据传输过程中可能产生的数据错误进行了检测,并抛弃已经损坏的数据。 

    UDP 套接字在使用前不需要进行连接。: UDP 套接字将保留边界信息。这个特性使应用程序在接受信息时,从某些方面来说比使用 TCP 套接字更简单。UDP 协议所提供的端到端传输服务是尽力而为( best-effort )的,即 UDP 套接字将尽可能地传送信息, 但并不保证信息一定能成功到达目的地址, 而且信息到达的顺序与其发送顺序不一定一致。

    使用UDP而不是用TCP原因:1.效率,2.灵活性

    Java 程序员通过 DatagramPacket 类和 DatagramSocket 类来使用 UDP 套接字。服务器端都使用 DatagramSockets 来发送数据,使用 DatagramPackets 来接收数据。 

    

    UDP 客户端首先向被动等待联系的服务器端发送一个数据报文。 一个典型的 UDP 客户端主要执行以下三步:

1. 创建一个 DatagramSocket 实例,可以选择对本地地址和端口号进行设置。

2. 使用 DatagramSocket 类的 send() receive() 方法来发送和接收 DatagramPacket 例,进行通信。

3. 通信完成后,使用 DatagramSocket 类的 close() 方法来销毁该套接字。 

 典型的 UDP 服务器要执行以下三步:

1. 创建一个 DatagramSocket 实例, 指定本地端口号, 并可以选择指定本地地址。 此时,服务器已经准备好从任何客户端接收数据报文。

2. 使用 DatagramSocket 类的 receive() 方法来接收一个 DatagramPacket 实例。当 receive() 方法返回时, 数据报文就包含了客户端的地址, 这样我们就知道了回复信息应该发送到什么地方。

3. 使用 DatagramSocket 类的 send() receive() 方法来发送和接收 DatagramPackets 实例,进行通信。 

客户端代码:

package com.iteye.xuj.socket;

import java.net.DatagramSocket;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.io.IOException;
import java.io.InterruptedIOException;

public class UDPTestClient {

	private static final int TIMEOUT = 3000;
	private static final int MAXTRIES = 5;

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

		InetAddress serverAddress = InetAddress.getByName("127.0.0.1");
		byte[] bytesToSend = "发送数据".getBytes();
		int servPort = 7;

		// 创建UDP套接字
		DatagramSocket socket = new DatagramSocket();
		// 设置套接字超时时间
		socket.setSoTimeout(TIMEOUT);

		// 创建发送的数据报文
		DatagramPacket sendPacket = new DatagramPacket(bytesToSend, bytesToSend.length, serverAddress, servPort);
		// 创建接收的数据报文
		DatagramPacket receivePacket = new DatagramPacket(new byte[bytesToSend.length], bytesToSend.length);

		// 发送数据报文
		int tries = 0;
		boolean receivedResponse = false;
		do {
			// 发送数据报文
			socket.send(sendPacket);
			// 处理数据报文的接收
			try {
				socket.receive(receivePacket);

				if (!receivePacket.getAddress().equals(serverAddress)) {

					throw new IOException("Received packet from an unknownsource");
				}
				receivedResponse = true;
			} catch (InterruptedIOException e) {
				tries += 1;
				System.out.println("Timed out, " + (MAXTRIES - tries) + " more tries...");
			}
		} while ((!receivedResponse) && (tries < MAXTRIES));// 最多发送多少次

		if (receivedResponse) {
			System.out.println("Received: " + new String(receivePacket.getData()));
		} else {
			System.out.println("No response -- giving up.");
		}
		// 关闭套接字
		socket.close();
	}
}

 

服务器端代码:

package com.iteye.xuj.socket;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPTestServer {

	private static final int ECHOMAX = 255;

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

		int servPort = 7;

		// 创建和设置数据报文套接字
		DatagramSocket socket = new DatagramSocket(servPort);
		// 创建数据报文
		DatagramPacket packet = new DatagramPacket(new byte[ECHOMAX], ECHOMAX);

		// 迭代处理收到的回馈请求
		while (true) {
			// 接收回馈请求数据报文
			socket.receive(packet);
			System.out.println("Handling client at " + packet.getAddress().getHostAddress() + " on port " + packet.getPort());
			// 发送回馈信息
			socket.send(packet);
			// 重置缓存区大小
			packet.setLength(ECHOMAX);
		}
	}
}

 

在服务端的socket.receive(packet);处设置断点,用Debug模式运行,

连续运行两次客户端,再将服务端断点去掉,按F8让服务端运行:

服务端输出:

Handling client at 127.0.0.1 on port 50906
Handling client at 127.0.0.1 on port 50907
Handling client at 127.0.0.1 on port 50906
Handling client at 127.0.0.1 on port 50907
Handling client at 127.0.0.1 on port 50906

 

首先运行的客户端输出:

Timed out, 4 more tries...
Timed out, 3 more tries...
Received: 发送数据

 其次运行的客户端输出:

Timed out, 4 more tries...
Received: 发送数据

 

如果客户端修改以下代码:

byte[] bytesToSend = "发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长".getBytes();

 则运行客户端后输出为:

Received: 发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发送数据很长发

 发现数据被截断。

猜你喜欢

转载自xujava.iteye.com/blog/1894738