一.UDP 协议简介

UPD协议 是常见的 网络传输协议之一, 当然另1个是TCP协议.

UPD协议 是一种不靠的协议.

是因为发送方不会关心接受方的状态, 直接向接收方发送数据包, 也就是说这个数据包有可能因为对方不在线而丢失.

二. Java UDP编程的几个关键的类(或数组).

1. Byte[], 字节数组, 在UDP协议中, 任何数据(图片, 字符..) 都必须转化成ByteArray.

字节数组相当与要发送或接受的货物.

2. DatagramPacket, 字节数组不能网络在传输,  就如货物不能直接在海上运输一样.

DatagramPacket 就相当于1个容器或集装箱, 我们可以把字节数组放在这个容器, 然后在容器上贴上关键的信息.(目标地址和端口号)

就如我们call顺丰必须要事先把物品打包, 写上地点和收件人一样, 道理很简单.

DatagramPacket 就是所谓的数据包, 把字节数组放入DatagramPacket的行为就叫数据打包.

3. DatagramSocket,  这个类相当与1个码头, 码头与发送和接受集装箱(DatagramPacket), 但是码头不会直接发送和接受货物(ByteArray).

4. InetAddress, 这个是java中表示ip地址的1个类.

它没有提供公开的构造函数, 但是它提供静态方法getByName(String ip)来返回1个静态对象(singleTone).

一般我们会将1个InetAddress对象贴到DatagramPacket对象上.

5. ByteAarryInputStream, ByteArrayOutputStream, DataInputStream, DataOutputStream...

这个些流是把各种类型的数据转换为字节数组的工具.

也就是说.

a. 所有的要发送的数据都必须转换成字节数组.

b. 所有要发送的字节数组都必须打包(DatagramPacket), 并贴上目标ip, 和端口.

c. 所有的DatagramPacket都必须经过DatagramSocket来发送或接受.

三. DatagramSocket 简介

上面说过了,  这个类相当于1个发送和接受集装箱(DatagramPacket)的码头.

下面介绍若干个它的关键方法.

3.1 DatagramSocket()

首先介绍构造方法, 这个构造方法是不带任何参数的(ip, 端口).

这个构造方法一般用于构造1个发送端的码头,  它可以向各个目标ip和端口发送数据包, 前提是目标ip和端口都附加在数据包(DatagramPacket).

3.2 DatagramSocket(int port)

构造1个DatagramSocket对象同时绑定端口.

这个方法一般用于构造接收数据包(DatagramPacket)的码头. 表示只接受指定端口的数据包.

原理很简单, 例如你发邮件, 可以向不同邮箱发送地址, 但是你只会接受发给你自己的邮件.

3.3 send(DatagramPacket dp)

将1个数据包发送出去, 发送哪里? 取决于数据包上面的ip和端口信息.

注意, 参数dp必须具有目标ip, 端口信息, 否则回throw Exception.

3.4 receive(DatagramPacket dp)

用1个数据包(集装箱)来接受发送过来的数据,  也就是dp这个参数的值会被修改.

这个方法一旦被执行, 程序会等待(hold 住), 知道收到1个数据包为止.

3.5 close()

关闭这个码头, DatagramSocket使用完后可以执行close()来释放资源, 注意一旦close(), 就不能重新打开, 就如stream一样.

四. DatagramPacket 简介

上面提到过了, DatagramPacket 实际上是1个存放字节数组的容器.  并可以贴上ip和端口信息用于发送.

下面也介绍若干个关键方法.

4.1 DatagramPacket(byte[] buf, int length)

首先也是构造方法, DatagramPacket并没有提供参数为空的构造方法, 而且各个构造方法必须有1个字节数组参数.

这个字节数组就是DatagramPacket的内核数组.

也就是说, 我们不能构造1个为"空"的DatagramPacket.

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

但是我们可以用别的字节数组来替换掉原来的内核字节数组, 就是用这个setData方法了, 这个方法一般用于发送端, 在编程中, 我们可以利用同1个DatagramPacket对象来不断发送不同的数据.

int offset, int length这个参数是指定 byteArray中的有效数据起始位置和长度.

4.3 setAddress(InetAddress iaddr)

为包裹贴上目标ip地址, 一般用于发送端.

注意参数是1个对象, 也就是我们必须实现构造1个InetAddress对象, 上面有提过.

4.4 setPort(int port)

为包裹贴上端口信息, 例如发送包裹到太古汇1座12F 汇丰公司(ip), 但是里面很多人啊, 谁来收呢. 所以还有加上收件人信息啊(port)

4.5 byte[] getData()

返回内核数组, 也就是把货物从包裹中提取出来啦, 一般用于接收端.

这得注意的是, DatagramPacket这个容器一般可以重复利用.

对于发送端来讲很简单, 不断利用setData(byte[] bArr)来替换内核数组(货物)就ok了.

但是对于接受来讲, DatagramPacket .的内核数组会用于接受数据.

那么这个内核数组的高位位置可能存在上次接受的数据.

DatagramPacket并没有提供重置内核数组的方法.

所以我们需要用Arrays.fill()方法来手动重置它的内核数组(当然你也可以在接受前利用setData()来给它1个新的内核数组).

五. 一个UPD编程例子.

这个例子很简单, 无非1个发送端放在本机, 1个接收端放在另1台机器.

发送端会可以发送字符串(消息)给接受端, 接收端回在终端上显示这个信息.

这个程序有四个类.

分别是

UDP_Server1.java     ->   接收端

UPD_SocketReceive    ->   接收端调用这个类来接受数据

UPD_Client1.Java      ->  发送端

UDP_SocketSend      ->   发送端调用这个类来发送数据.

5.1 UDP_SocketSend 

这个类的提供下面关键方法:

start()      执行这个方法后, 可以发送数据.

send(byte[] bArr,int sLength, String ip, int port)    发送字节数组到指定ip 和端口

close()     关闭这个socket.

代码如下:

package UDP_kng;import java.net.*;
import java.io.*;public class UDP_SocketSend{private boolean startedFlag;private InetAddress ipSend;private DatagramSocket dataSocket; //it just like a wharf or portprivate DatagramPacket dataPacket = new DatagramPacket(new byte[1],0); //it just like a containerpublic UDP_SocketSend(){this.startedFlag = false;}    //build a wharfpublic int start(){if (true == this.startedFlag){System.out.println("Err: This UDP Client is started..");return -2;}try{dataSocket = new DatagramSocket();System.out.println("This socket started successfully!!");}catch(Exception e){e.printStackTrace();System.out.println("Err: Failed to instantiate a UDP Socket..!!");return -1;}this.startedFlag = true;return 0;}public int close(){if (false == this.startedFlag){System.err.println("Err: The socket is not started yet!");return -2;}try{dataSocket.close();  //once the socket is closed, it cannot be reopen, we hava to new another socket if we want to sendout data.System.out.println("this socket closed successfully!!");}catch(Exception e){e.printStackTrace();System.err.println("Err: Fail to close the Socket!!");return -1;}this.startedFlag = false;return 0;}public int send(byte[] bArr,int sLength, String ip, int port){if (false == this.startedFlag){System.err.println("Err: The socket is not started yet!");return -2;}if (0 >= port){System.err.println("Err: The port provided is not vaild!");return -1;}try{ipSend = InetAddress.getByName(ip); }catch(Exception e){System.err.println("Err: Failed to setup the ip address!");}dataPacket.setPort(port); //attach a labeldataPacket.setData(bArr,0,sLength); //put the data into this containerdataPacket.setAddress(ipSend);try{dataSocket.send(dataPacket);  //send out the container to ipSend}catch(Exception e){e.printStackTrace();System.err.println("Err: Failed to send out the data package!");return -3;}return 0;}}

5.2 UDP_Client1

这个类调用上面的UDP_SocketSend,可以不断地让用户发送消息到制定的ip和端口.

代码:

package UDP_kng;import java.net.*;
import java.io.*;
import UDP_kng.*;public class UDP_Client1{private static int port = 9001;//private static String ip = "127.0.0.1";private static String ip = "192.168.1.106";public static void f() throws Exception{ByteArrayOutputStream bas = new ByteArrayOutputStream();    DataOutputStream dos = new DataOutputStream(bas);DataInputStream dis = new DataInputStream(System.in);UDP_SocketSend uSender = new UDP_SocketSend();uSender.start();System.out.println("Please input your message, type EOF to exit.");String msg = dis.readLine();while(!msg.equals("EOF")){bas.reset();dos.writeBytes(msg);dos.flush();uSender.send(bas.toByteArray(), bas.size(),ip, port);System.out.println("Please input your message, type EOF to exit.");msg = dis.readLine();}uSender.close();dos.close();dis.close();//uSender.send(dstream.toByteArray(),"127.0.0.1", port);}
}

5.3 UDP_SocketReceive

这个类提供receive()方法, 返回1个DatagramPacket数据包.

package UDP_kng;import java.net.*;
import java.util.Arrays;public class UDP_SocketReceive{private DatagramSocket dataSocket; //just like a wharfprivate byte[] bArr = new byte[1024];private DatagramPacket dataPacket = new DatagramPacket(bArr,bArr.length); //just like a containerprivate int port;private boolean startedFlag = false;public UDP_SocketReceive(int port){this.port = port;this.start(); } public int start(){if (true == startedFlag){System.err.println("This socket is stated already!");return -1;}try{dataSocket = new DatagramSocket(this.port);}catch(Exception e){e.printStackTrace();System.err.println("fail to new a DatagramSocket, please try to start once again!");this.startedFlag = false;return -2;}this.startedFlag = true;return 0;} public DatagramPacket receive(){if (false == startedFlag){System.err.println("This socket is not stated yet!");return null;}byte b = 0;Arrays.fill(bArr,b); //clean the dataPacket, avoid to show previous data.try{dataSocket.receive(this.dataPacket);//after this step, the container have got the data from sender.}catch(Exception e){e.printStackTrace();System.err.println("Failed receive a datapackage!");return null;}return dataPacket;}}

5.4 UDP_SocketServer1

这个类不断循环调用上面那个UDP_SocketReceive 来接受数据包, 实际上就是在监听制定的端口, 一旦接受到数据包, 就把数据包里的数据转化为字符串输出到终端.

package UDP_kng;import UDP_kng.*;
import java.io.*;
import java.net.*;public class UDP_Server1{public static int port = 9001;public static void f() throws Exception{DatagramPacket dataPacket;UDP_SocketReceive uReceiver = new UDP_SocketReceive(port);while(true){System.out.println("Listening port....");dataPacket =  uReceiver.receive();printMsg(dataPacket);        }}public static void printMsg(DatagramPacket dataPacket) throws Exception{ByteArrayInputStream bis = new ByteArrayInputStream(dataPacket.getData());DataInputStream dis = new DataInputStream(bis);String msg = dis.readLine();System.out.println("msg: " + msg);dis.close();}}

5.5 执行结果

将编译后的UDP_Server1 放在虚拟机的xp里执行(java跨平台),  UDP_Client1放在本机执行, 如下:

5.6 小结


上面例子的功能十分简单, 一端只能发送, 一端只能接受, 但是如果我们利用多线程,  在两端都打开发送和接受线程, 就相当于1个简单的UDP聊天工具了..


Java UDP 编程简介.相关推荐

  1. java UDP 编程

    java UDP 编程 DatagramSocket的构造器. DatagramSocket(int port, InetAddress laddr):创建一个DatagramSocket实例,并将该 ...

  2. Java并发编程简介

    并发编程简介 1. 什么是并发编程 所谓并发编程是指在一台处理器上"同时"处理多个任务.并发是在在同一实体上的多个事件.多个事件在同一时间间隔发生. 并发编程 ①从程序设计的角度来 ...

  3. Java多线程开发(一)Java多线程编程简介

    文章目录 参考 Java线程简介 Thread类构造方法和属性 常用Thread类方法 线程的生命周期 多线程编程的优势和风险 安全性问题 活跃性问题 性能问题 参考 [Java并发系列01]Thre ...

  4. Java TCP 编程简介

    一.TCP 协议简介 http://blog.csdn.net/nvd11/article/details/40954043 之前的博文简单介绍了网络编程中的UDP协议 其实更常用的网络协议是TCP协 ...

  5. java机器人编程简介_机器人十大流行编程语言的介绍及机器人编程系统以及操作方法...

    "如果您问"机器人的最佳编程语言是什么?计算机视觉程序员会给出不同于认知机器人的答案.每个人都不同意什么是"最好的编程语言",语言首先学习,即使这是最现实的答案 ...

  6. Java网络编程:TCP,UDP,sock编程

    第一节 网络基础知识 常用的通信协议 MAC地址:(Media Access Control Address,媒体存取控制位址), IP:(Internet Protocol,网际协议) UDP:(U ...

  7. Java刷题知识点之TCP、UDP、TCP和UDP的区别、socket、TCP编程的客户端一般步骤、TCP编程的服务器端一般步骤、UDP编程的客户端一般步骤、UDP编程的服务器端一般步骤...

    TCP和UDP是两个传输层协议,广泛应用于网络中不同主机之间传输数据.对任何程序员来说,熟悉TCP和UDP的工作方式都是至关重要的.这就是为什么TCP和UDP是一个流行的Java编程面试问题. Jav ...

  8. 【Java 并发编程】CountDownLatch 简介

    文章目录 I CountDownLatch 概念 II CountDownLatch 使用流程 III CountDownLatch API 简介 I CountDownLatch 概念 1. 概念 ...

  9. JAVA通信编程(四)——UDP通讯

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

最新文章

  1. 史上最大“云办公”实验开始,你参加了吗?
  2. 浙师大dns服务器地址
  3. java多线程init,Java多线程 - 线程 - 初识
  4. 智能卡门禁管理系统_综合门禁管理信息系统相关技术及未来准备
  5. matlab多项式加法运算,matlab多项式运算与代数方程求解解析.ppt
  6. PS Raw增效工具 - Adobe Camera Raw14 for mac
  7. MXNet——symbol
  8. DXUT框架剖析(8)
  9. C# ComBox 垂直滚动条
  10. C专家编程--随记(二)
  11. 通信基础 7 —— 遍历保密速率、谱分解物理意义
  12. 有道智云翻译API + retrofit实现在线翻译Android app
  13. python中ix用法_Python:Pandas中的ix用法详细解释
  14. 解析阿里“聚石塔”产品
  15. 台式机和计算机有什么区别,笔记本电脑和台式电脑有什么区别
  16. c++ 可变参数 log 打印函数实现
  17. 站长技术导航二开美化网站源码 网站提交自动秒收录
  18. 大学的治理与改革—张维迎
  19. 搜索引擎优化,SEO关键词快速排名方法有哪些?
  20. 游戏运营分析项目(1)

热门文章

  1. [力扣leetcode39]组合总和及回溯法
  2. 【Pygame小游戏】这款经典的炸弹人超能游戏上线,你爱了嘛?(附源码)
  3. 密码篇——对称加密—AES
  4. 蓝队视角下的企业安全运营
  5. MFC实现获取鼠标位置的小程序
  6. 006 技能数组分析和代码编写
  7. MySQL创建索引(CREATE INDEX)
  8. 1119 Pre- and Post-order Traversals (30 分)【难度: 难 / 知识点: 树的构建】
  9. 1022 Digital Library (30 分) 【难度: 中 / 知识点: 哈希表】
  10. 【PAT乙级】1054 求平均值 (20 分)