Java TCP/IP Socket 编程 笔记(三)—UDP的例子

http://jimmee.iteye.com/blog/617110

 

Java TCP/IP Socket 编程 笔记(三)—UDP的例子
  • 博客分类:
  • J2SE
1.UDP套接字与TCP套接字不同。UDP套接字在使用前不需要进行连接。 TCP协议与电话通信相似,而UDP协议则与邮件通信相似:你寄包裹或信件时不要进行“连接”,但是你的为每个包裹和信件制定目的地址。类似地,每条信息(datagram,即数据报文)负载了自己的地址信息,并与其他信息相互独立。在接收信息时,UDP套接字扮演的角色就像是一个信箱,从不同地址发送来的信件和包裹都可以放到里面。一旦被创建,UDP套接字就可以用来连续地向不同的地址发送消息,或从任何地址接收信息。
UDP套接字将保留边界信息。UDP不像TCP一样,它是尽可能地传送消息,但并不保证信息一定能成功到达目的地址,而且信息到达的顺序与其发送顺序不一定一致(就像通过邮政部分寄信一样)。因此,UDP套接字的程序必须准备好处理信息的丢失和重排。
UDP的优点之一是效率较高,其次是灵活性。

Java通过DatagramPacket类和DatagramSocket类来使用UDP套接字。客户端和服务端都使用DatagramSocket来发送数据,使用DatagramPacket来接收数据。

发送信息时,Java程序创建一个包含了待发送信息的DatagramPacket实例,并将其作为参数传递给DatagramSocket类的send()方法。接收信息时,Java程序首先创建一个DatagramPacket类的实例,该实例中预先分配了一些空间(一个字节数组byte[]),并将接收到的信息存放在该空间中。然后把该实例作为参数传递给DatagramSocket类的receive()方法。


DatagramPacket的内部有length和offset字段,如果指定了offset,数据报文的数据部分将从字节数组的指定位置发送或接收数据。length参数指定了字节数组中在发送时要传输的字节数,活在接收数据时所能接收的最多字节数。length要比data.length小,但不能比它大。

UDP客户端:
Java代码 复制代码 收藏代码
  1. import java.io.IOException;
  2. import java.io.InterruptedIOException;
  3. import java.net.DatagramPacket;
  4. import java.net.DatagramSocket;
  5. import java.net.InetAddress;
  6. public class UDPEchoClientTimeout {
  7. private static final int TIMEOUT=3000;
  8. private static final int MAXTRIES=5;
  9. public static void main(String[] args) throws IOException {
  10. if(args.length<2||args.length>3){
  11. throw new IllegalArgumentException("Parameter(s):<Server> <Word> [<Port>]");
  12. }
  13. InetAddress serverAddress=InetAddress.getByName(args[0]);//server address;
  14. byte [] bytesToSend=args[1].getBytes();
  15. int servPort=(args.length==3)?Integer.parseInt(args[2]):7;
  16. //1.创建一个DatagramSocket实例,可以选择对本地地址和端口进行设置。
  17. DatagramSocket socket=new DatagramSocket();
  18. //设置receive()方法的最长阻塞时间
  19. socket.setSoTimeout(TIMEOUT);
  20. DatagramPacket sendPacket=new DatagramPacket(bytesToSend,bytesToSend.length,serverAddress,servPort);
  21. DatagramPacket receivePacket=new DatagramPacket(new byte[bytesToSend.length],bytesToSend.length);
  22. int tries=0;
  23. boolean receivedResponse=false;
  24. do{
  25. //2.使用DatagramSocket类的send()和receive()方法来发送和接收DatagramPacket实例,进行通信
  26. socket.send(sendPacket);
  27. try{
  28. socket.receive(receivePacket);
  29. if(!receivePacket.getAddress().equals(serverAddress)){
  30. throw new IOException("Received packet from an unknown source");
  31. }
  32. receivedResponse=true;
  33. }catch(InterruptedIOException e){
  34. tries+=1;
  35. System.out.println("Timed out,"+(MAXTRIES-tries)+" more tries ...");
  36. }
  37. }while(!receivedResponse&&(tries<MAXTRIES));
  38. if(receivedResponse){
  39. System.out.println("Received: "+new String(receivePacket.getData()));
  40. }else{
  41. System.out.println("No response -- giving up.");
  42. }
  43. //3.通信完成后,使用DatagramSocket类的close方法来销毁该套接字
  44. socket.close();
  45. }
  46. }
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 MAXTRIES=5;
	
	public static void main(String[] args) throws IOException {
		if(args.length<2||args.length>3){
			throw new IllegalArgumentException("Parameter(s):<Server> <Word> [<Port>]");
		}
		
		InetAddress serverAddress=InetAddress.getByName(args[0]);//server address;
		byte [] bytesToSend=args[1].getBytes();
		int servPort=(args.length==3)?Integer.parseInt(args[2]):7;
		
		//1.创建一个DatagramSocket实例,可以选择对本地地址和端口进行设置。 
		DatagramSocket socket=new DatagramSocket();
		//设置receive()方法的最长阻塞时间
		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{
			//2.使用DatagramSocket类的send()和receive()方法来发送和接收DatagramPacket实例,进行通信
			socket.send(sendPacket);
			try{
				socket.receive(receivePacket);
				if(!receivePacket.getAddress().equals(serverAddress)){
					throw new IOException("Received packet from an unknown source");
				}
				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.");
		}
		
		//3.通信完成后,使用DatagramSocket类的close方法来销毁该套接字
		socket.close();
	}
}


UDP的服务器端:
Java代码 复制代码 收藏代码
  1. import java.io.IOException;
  2. import java.net.DatagramPacket;
  3. import java.net.DatagramSocket;
  4. public class UDPEchoServer {
  5. private static final int ECHOMAX=255;//max size of echo datagram
  6. public static void main(String[] args) throws IOException {
  7. if(args.length!=1){
  8. throw new IllegalArgumentException("Parameter(s):<Port>");
  9. }
  10. int servPort=Integer.parseInt(args[0]);
  11. //1.创建一个DatagramSocket实例,指定本地端口号,可以选择指定本地地址
  12. DatagramSocket socket=new DatagramSocket(servPort);
  13. DatagramPacket packet=new DatagramPacket(new byte[ECHOMAX],ECHOMAX);
  14. while(true){
  15. //2.使用DatagramSocket的receive方法来接收一个DatagramPacket实例。
  16. socket.receive(packet);
  17. System.out.println("Handling client at "+packet.getAddress().getHostAddress()+" on port "+packet.getPort());
  18. socket.send(packet);
  19. packet.setLength(ECHOMAX);
  20. }
  21. }
  22. }
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class UDPEchoServer {
	private static final int ECHOMAX=255;//max size of echo datagram
	
	public static void main(String[] args) throws IOException {
		if(args.length!=1){
			throw new IllegalArgumentException("Parameter(s):<Port>");
		}
		
		int servPort=Integer.parseInt(args[0]);
		
		//1.创建一个DatagramSocket实例,指定本地端口号,可以选择指定本地地址
		DatagramSocket socket=new DatagramSocket(servPort);
		DatagramPacket packet=new DatagramPacket(new byte[ECHOMAX],ECHOMAX);
		
		while(true){
			//2.使用DatagramSocket的receive方法来接收一个DatagramPacket实例。
			socket.receive(packet);
			System.out.println("Handling client at "+packet.getAddress().getHostAddress()+" on port "+packet.getPort());
			
			socket.send(packet);
			packet.setLength(ECHOMAX);
		}
	}
}


注意:DatagramPacket的getData()方法的使用,它返回数据缓冲区,是一个字节数组,需要注意。
packet.setData(buf, offset,length);设置了接收数据时放到缓存去buf中的位置
,因此接收的数据new String(packet.getData(),packet.getOffset(),packet.getLength())的方式构造的。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值