java TCP/IP Socket编程-----基本套接字-----UDP通讯-----笔记6

来源:互联网 发布:dota2职业选手 数据 编辑:程序博客网 时间:2024/05/31 19:23

概述:

UDP协议提供了一种不同于TCP协议的端到端服务。实际上UDP协议只实现两个功能:

1)在IP协议的基础上添加了另一层地址(端口),

2)对数据传输过程中可能产生的数据错误进行了检测,并抛弃已经损坏的数据。由于其简单性,UDP套接字具有一些与我们之前所看到的TCP套接字不同的特征。例如,UDP套接字在使用前不需要进行连接。TCP协议与电话通信相似,而UDP协议则与邮件通信相似:你寄包裹或信件时不需要进行"连接",但是你得为每个包裹和信件指定目的地址。类似的,每条信息(即数据报文,datagram)负载了自己的地址信息,并与其他信息相互独立。在接收信息时,UDP套接字扮演的角色就像是一个信箱,从不同地址发送来的信件和包裹都可以放到里面。一旦被创建,UDP套接字就可以用来连续地向不同的地址发送信息,或从任何地址接收信息。

1.API了解

DatagramPacket:创建

DatagramPacket(byte[ ] data, int length)

DatagramPacket(byte[ ] data, int offset, int length)

DatagramPacket(byte[ ] data, int length, InetAddress remoteAddr, int remotePort)

DatagramPacket(byte[ ] data, int offset, int length, InetAddress remoteAddr, int remotePort)

DatagramPacket(byte[ ] data, int length, SocketAddress sockAddr) DatagramPacket(byte[ ] data, int offset, int length, SocketAddress sockAddr)


DatagramPacket:地址处理

InetAddress getAddress() 

void setAddress(InetAddress address) 

int getPort() 

void setPort(int port) 

SocketAddress getSocketAddress()

void setSocketAddress(SocketAddress sockAddr)


DatagramPacket 处理数据

int getLength() 

void setLength(int length) 

int getOffset() 

byte[ ] getData()

 void setData(byte[ ] data) 

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

2.UDP客户端:

UDP客户端首先向被动等待联系的服务器端发送一个数据报文。一个典型的UDP客户端主要执行以下三步:
1. 创建一个DatagramSocket实例,可以选择对本地地址和端口号进行设置。
2. 使用DatagramSocket类的send() 和 receive()方法来发送和接收DatagramPacket实例,进行通信。
3. 通信完成后,使用DatagramSocket类的close()方法来销毁该套接字。

与Socket类不同,DatagramSocket实例在创建时并不需要指定目的地址。这也是TCP协议和UDP协议的最大不同点之一。在进行数据交换前,TCP套接字必须跟特定主机和另一个端口号上的TCP套接字建立连接,之后,在连接关闭前,该套接字就只能与相连接的那个套接字通信。而UDP套接字在进行通信前则不需要建立连接,每个数据报文都可以发送到或接收于不同的目的地址。(DatagramSocket类的connect()方法确实允许指定远程地址和端口,但该功能是可选的

如果超过了指定时间仍未得到响应,客户端就会重发回馈请求。我们的回馈客户端执行以下步骤:
1. 向服务器端发送回馈字符串。
2. 在receive()方法上最多阻塞等待3秒钟,在超时前若没有收到响应,则重发请求(最多重发5次)。
3. 终止客户端。

package com.tcp.ip.chapter2;import java.io.IOException;import java.io.InterruptedIOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class UDPEchoClientTimeout {private static final int TIMEOUT = 3000;private static final int MAXRIES = 5;public static void main(String[] args) throws Exception {if((args.length < 2) || (args.length > 3)) {throw new IllegalArgumentException("Parameter(s) : <Server> <Word> [<Port>]");}InetAddress serverAddress = InetAddress.getByName(args[0]);byte [] bytesToSend = args[1].getBytes();int servPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7;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," + (MAXRIES-tries) + " more tries");}}while ((!receivedResponse) && (tries < MAXRIES));if(receivedResponse) {System.out.println("接受数据成功:" + new String(receivePacket.getData()));}else {System.out.println("接受数据失败");}socket.close();}}
2.常用的API

DatagramSocket: 创建
DatagramSocket() 

DatagramSocket(int localPort)

 DatagramSocket(int localPort, InetAddress localAddr)


DatagramSocket: 连接与关闭
void connect(InetAddress remoteAddr, int remotePort) 

void connect(SocketAddress remoteSockAddr) 

void disconnect()

void close()

DatagramSocket: 地址处理
InetAddress getInetAddress() 

int getPort() 

SocketAddress getRemoteSocketAddress()

 InetAddress getLocalAddress()

 int getLocalPort() SocketAddress

 getLocalSocketAddress()


DatagramSocket: 发送和接收
void send(DatagramPacket packet) 

void receive(DatagramPacket packet)

DatagramSocket: 选项
int getSoTimeout() 

void setSoTimeout(int timeoutMillis)

3.UDP服务器端

典型的UDP服务器要执行以下三步:
1. 创建一个DatagramSocket实例,指定本地端口号,并可以选择指定本地地址。此时,服务器已经准备好从任何客户端接收数据报文。
2. 使用DatagramSocket类的receive()方法来接收一个DatagramPacket实例。当receive()方法返回时,数据报文就包含了客户端的地址,这样我们就知道了回复信息应该发送到什么地方。
3. 使用DatagramSocket类的send() 和receive()方法来发送和接收DatagramPackets实例,进行通信。

package com.tcp.ip.chapter2;import java.net.DatagramPacket;import java.net.DatagramSocket;public class UDPEchoServer {private static final int ECHOMAX = 255;public static void main(String[] args) throws Exception {if(args.length != 1) {throw new IllegalArgumentException("Parameter(s): <Port>");}int servPort = Integer.parseInt(args[0]);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);}}}
DatagramSocket就是像快递员,没有打电话通知你,可能第一次他去你家,你不在,他就是回去了,下一次再来,你又不在家,一直到⑤次还不在,他认为你拒收了。

阅读全文
0 0
原创粉丝点击