这是张富涛的第8篇原创
网络编程:UDP编程(1)
1. 概述
在网络编程中,TCP可以理解为打电话,而UDP(User Datagram Protocol)则可以理解为发短信、发快递,发短信和发快递有一个共同点,发送的时候无需知道接收方存不存在,所以对于发送方来说,有可能会有“发送的消息”对方接收不到的损失,这相对于类似打电话的“TCP”方式来说,稍显得不靠谱一些。 所以对于我们平时重要的事情都会想着:“打个电话给对方吧!”,而平时我们一般重要的事情就是用发短信来解决了。
对于UDP的方式,由于无需像TCP一样建立“专用的网络连接”等优点,对于服务器压力也更小,属于一种“物美价廉”的通讯方式,而也因为这些优点,UDP的编程方式也跟TCP不太一样。那么下面我们就来看一下UDP编程需要的工具类吧!
使用到的类
UDP编程在Java语言中也受到了很好的支持与封装,主要用到的类有两个:
java.net.DatagramSocket:
UDP编程中,作为客户端和服务器端都需要的类,虽然UDP不像TCP一样需要建立“专用的网络连接”,但是一样需要建立连接进行接收和发送数据,所以主要需要的就是这个类了,这个类既可以作为客户端发送、接收数据包的类,也可以作为服务器端发送、接收数据包的类。
java.net.DatagramPacket:
UDP编程中发送的数据包,UDP发送数据时不依赖于IO流,而是将ip、端口号、发送数据封装在包里进行发送。而这就是数据的载体。我们对于客户端和服务器端发送接收数据都是以这个类进行接收发送。我们可以将“java.net.DatagramSocket”理解为一个接收数据和发送数据的工具,而真正决定发送到哪个ip端口,发送什么东西的是“java.net.DatagramPacket”。
2. UDP客户端的实现
我们先简单回忆一下客户端编程步骤:
- 建立网络连接
- 交换数据
- 关闭网络连接
首先第一步是建立网络连接,对于客户端来说,它无需真正建立专用连接,可是需要建立一个接收发送的java.net.DatagramSocket类。
DatagramSocket datagramSocket = new DatagramSocket();
构造函数中什么都不传递,代表DatagramSocket为我们随机监听一个端口,在客户端我们可以这样使用。但是DatagramSocket类还有一种构造方法,传入一个ip,代表不随机监听一个端口,而是我们约定它监听一个固定的端口。
DatagramSocket datagramSocket2 = new DatagramSocket(10001);
我们在客户端没必要监听一个固定的端口,所以可以用第一种构造方法。
那么我们到了第二部“数据交换”了,首先我们介绍一下发送数据吧,发送数据时主要用到了java.net.DatagramPacket类,这个类在创建的时候需要将接受方(服务器端)的ip、端口和我们需要发送的数据封装进去。也正是DatagramPacket决定了发送于哪个服务器地址。
最终调用的是DatagramSocket对DatagramPacket进行发送。
然后是接收数据,在Java语言中,UDP的接收方式是我们需要先准备一个DatagramPacket对象,然后使用DatagramSocket对其进行接收,而我们准备DatagramPacket的时候需要一个缓冲数组最为构造函数,该数组用于存储接收的服务器端反馈数据,该数组的长度必须大于或等于服务器端响应的实际有效数据的长度。
这样我们就可以拿到服务器返回的数据,并且展示了。
最后我们需要关闭DatagramSocket对象释放资源。
datagramSocket.close();
下面我们整合一下代码,做一个简单的客户端吧(图片太糊了,很抱歉给您不好的体验,后续的文章我会优化的):
以上代码由于没有服务器端进行配合,所以目前仅是演示使用,还没办法达到实用级别。下面就让我们来介绍服务器端的写法,让这段代码输出"服务器向你说:Hi,Good boy!
"吧!
3. UDP服务器端实现
我们先回忆一下服务器端的开发模型:
- 监听端口
- 获得连接
- 数据交换
- 关闭连接
首先是监听端口,服务器端监听端口依然需要java.net.DatagramSocket类,此时我们需要用到它的另一个构造方法。
DatagramSocket datagramSocket2 = new DatagramSocket(10001);
这样做的意义是:一般UDP通讯方式客户端作为首先连接服务器端的一方,需要知道服务器的ip、端口地址,而服务器拿到请求的ip、端口地址即可直接返回数据,我们在客户端不需要直接知道自己监听哪个端口。
接着服务器端就开始接收客户端发送过来的数据,其接收的方法和客户端接收数据的方法是一样的,其中receive方法的作用类似于TCP方式中accept方法的作用,该方法也是一个阻塞方法,其作用是接收数据。
接收到客户端发送过来的数据以后,服务器端对该数据进行逻辑处理,然后将响应数据再发送给客户端,而既然要发送给客户端,我们就需要知道客户端的ip和端口等数据,由于客户端发送数据的时候将这些封装到了请求包(DatagramPacket)里,我们正好可以从请求包里获取到这些数据。
最后释放资源的方式也是一样的,那么下面我们就看一下服务器端的代码实现吧:
这样我们就实现了一个简单的UDP客户端和服务器端了,我们看一下代码的执行结果吧,我们先运行服务器端监听端口等待客户端发送数据包过来,再运行客户端。
先启动服务器端结果:
启动客户端结果:
服务器结果:
图片被压缩的太糊了,很抱歉,后续我会优化的,请持续关注,谢谢!
---------------
公众号:张富涛的学习笔记(ID:futaoNT)
知乎:张富涛
CSDN:张富涛
这是一个在夜晚可以靠编程拯救世界的程序员,关注他将在第一时间获悉他的知识、工作心得!
长按下图二维码关注: