《Java TCP/IP Socket编程》读书笔记(4)

来源:互联网 发布:精灵软件下载 编辑:程序博客网 时间:2024/04/29 11:00

2.3 UDP套接字

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

UDP套接字与TCP套接字的不同点:

1. UDP协议在使用前不需要进行连接。

2. UDP协议保存边界信息。

2.3.1 UDP客户端

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

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

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

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


DatagramSocket创建的时候不需要指定目的地址。因为UDP通信前不需要进行连接。每个数据报可以发送到或者接收于不同的目的地址。

UDP协议的一个后果是会出现数据报文丢失。为了避免这个问题,可以设置最大阻塞时间。

下面一个UDP客户端的例子

package com.suifeng.tcpip.chapter2;import java.io.IOException;import java.io.InterruptedIOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;/** * UDP 客户端 *  * @author Suifeng *  */public class UDPEchoClientTimeout{// 超时时间private static final int TIMEOUT = 3000;// 最大连接次数private static final int MAXTRIES = 5;public static void main(String[] args) throws IOException{if (args.length < 2 || args.length > 3){throw new IllegalArgumentException("Paramters:<Server> <Word> [<Port>]");}// 服务器地址InetAddress serverAddress = InetAddress.getByName(args[0]);// 要发送的数据byte[] byteToSend = args[1].getBytes();// 服务器端口int serverPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7;// UDP客户端DatagramSocket socket = new DatagramSocket();// 接收数据阻塞时间socket.setSoTimeout(TIMEOUT);System.out.println("UDP 客户端已建立....");// 发送数据报包DatagramPacket sendPacket = new DatagramPacket(byteToSend,byteToSend.length, serverAddress, serverPort);// 接收的数据报包DatagramPacket receiverPacket = new DatagramPacket(new byte[byteToSend.length], byteToSend.length);// 尝试接收次数int tries = 0;boolean receivedResponse = false;do{System.out.println("向服务区端发送数据....");// 向服务器端发送数据socket.send(sendPacket);try{System.out.println("接收从服务器端返回的数据...");// 从服务器端接收数据socket.receive(receiverPacket);if (!receiverPacket.getAddress().equals(serverAddress)){throw new IOException("Received packet from an unknown source");}receivedResponse = true;}catch (InterruptedIOException e){tries++;System.out.println("Timed out," + (MAXTRIES - tries)+ " more ties");}} while ((!receivedResponse) && (tries < MAXTRIES));if(receivedResponse){System.out.println("Received:"+new String(receiverPacket.getData()));}else{System.out.println("No response--giving up!");}}}

2.3.2 UDP服务器端

TCP服务器一样,UDP服务器是建一个几个通信终端,并被动等待客户端发起连接。

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

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

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

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


下面的例子是使用UDP将客户端发送过来的消息会发给客户端的。

package com.suifeng.tcpip.chapter2;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;/** * UDP服务器端 *  * @author Suifeng *  */public class UDPEchoServer{// 最大显示数组字节数private static final int ECHO_MAX = 255;public static void main(String[] args) throws IOException{if (args.length != 1){throw new IllegalArgumentException("Parameter:<Port>");}// 服务器端口int serverPort = Integer.parseInt(args[0]);// 服务器端DatagramSocket socket = new DatagramSocket(serverPort);// 数据报DatagramPacket packet = new DatagramPacket(new byte[ECHO_MAX], ECHO_MAX);System.out.println("UDP服务器已启动....");while (true){System.out.println("正在等待客户端发送数据....");// 接收客户端发送的数据(阻塞)socket.receive(packet);System.out.println("Handing client at "+ packet.getAddress().getHostAddress() + " on port "+ packet.getPort());System.out.println("Received Data:"+new String(packet.getData()));// 向客户端发送数据(这里只是将数据包进行转发--透传,没有进行任何处理)socket.send(packet);// 重置缓存区大小packet.setLength(ECHO_MAX);}}}

先启用服务器端,监听39393端口


在启用客户端发送数据


再查看服务器端