聊聊UDP、TCP和实现一个简单的JAVA UDP小Demo
最近真的比较忙,很久就想写了,可是一直苦于写点什么,今天脑袋灵光一闪,觉得自己再UDP方面还有些不了解的地方,所以要给自己扫盲。
好了,咱们进入今天的主题,先列一下提纲:
1. UDP是什么,UDP适用于什么场景?
2. 写一个小Demo来加深一下UDP的理解。
3. UDP和TCP的区别有哪些?
4. TCP建连和关闭的过程,为什么建立连接的时候是三次握手,断开连接的时候需要四次?
1. UDP是什么,UDP适用于什么场景?
相信很多同学都听过UDP,UDP的全称:User Datagrame Protocol, 用户报文协议,是一个传输层协议。UDP最大的特点是:不可靠网络传输,无连接数据协议,即发送前不要连接,直接向目标地址发送。而TCP和UDP基本上是相互补充的,TCP是可靠的数据数据传输,基于连接后的数据发送。
TCP是Transmission Control Protocol,传输控制协议,TCP是基于可靠的数据传输,那么就需要牺牲更多的延迟和网络带宽。而UDP则不需要可靠的数据传输,那么将会需要更小的网络延迟和网络开销。UDP可以允许丢弃延迟的数据包。由于低延迟低带宽,所以UDP非常适合电脑游戏,语音电话,视频电话,网络直播。
我们接下来看一下UDP的Packet的组成(图片来源网络),8字节的Header,然后就是UDP的数据。本机如果作为客户端的话,本机的端口号为0-65535,也就是本机连接外部机器的话最多可以连接65536,0是保留端口号。如果作为服务端的话,可以使用的端口为2的32次方个端口。也就是可以接收的数据可以有这么多。当然,目前一台机器能处理的数据没有这么多。
8字节的Header,很简单也比较少,不像TCP需要20-60字节的数据。
Source port,源端口号,16位2个字节。
Length, 数据的长度2个字节。
Distination port, 目标端口,用于识别到目标机器的端口号。2个字节。
Checksum, 用于计算Header的Checksum(校验值)。
2. 写一个小Demo来加深一下UDP的理解。
1) UDP的服务端代码,因为UDP的代码都是JDK自带的,所以也不需要引入其他jar包就可以。
2)Server端主要创建步骤:
a) 创建一个监听udp的端口号 8888.
b) 创建一个用于接收数据的DatagramPacket,参数有两个,一个是数据,一个是数据的长度。
c) 采用循环进行receive数据,直到收到的bye字符串。
package myflink.udp; import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket; /**
* @author huangqingshi
* @Date 2020-05-24
*/
public class UDPServer { public static void main(String[] args) throws IOException { //1. 创建一个监听8888端口的udp socket
DatagramSocket ds = new DatagramSocket(8888);
//设置接收数据的最大值
byte[] receive = new byte[65535]; //用于接收的数据
DatagramPacket datagramPacket = null; while(true) {
//2. 创建一个用于接收数据。buf即数据和其长度
datagramPacket = new DatagramPacket(receive,receive.length ); //3. 接收byteBuff的数据
ds.receive(datagramPacket); System.out.println("Client:-" + data(receive)); //4. 如果接收到了bye,程序结束
if("bye".equals(data(receive))) {
break;
} //5.清理receive中的数据
receive = new byte[65535]; }
} public static StringBuilder data(byte[] bytes) {
if(bytes == null) {
return null;
} StringBuilder ret = new StringBuilder(); int i = 0;
while (bytes[i] != 0)
{
ret.append((char) bytes[i]);
i++;
}
return ret;
} }
3)接下来是客户端的代码,步骤如下:
a) 创建scanner用于在控制台进行数据输入,然后创建一个DatagramSocket用于处理数据。
b) 创建一个DatagramPacket用于数据的发送。
c) 进行数据发送。
d) 持续发送数据,当收到bye字符串的话就会结束。
package myflink.udp; import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner; /**
* @author huangqingshi
* @Date 2020-05-24
*/
public class UDPClient { public static void main(String[] args) throws IOException { Scanner scanner = new Scanner(System.in); InetAddress ip = InetAddress.getLocalHost(); //1. 创建一个socket对象用于处理数据
DatagramSocket socket = new DatagramSocket(); //用于存放数据
byte[] buf = null; //一个死循环,用于接收数据后处理,收到bye后结束处理
while(true) {
String input = scanner.nextLine();
//将接收到的信息转换为byte数组
buf = input.getBytes(); //2. 创建一个DatagramPack包用于创建发送的数据
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length, ip, 8888); //3. 发送数据
socket.send(datagramPacket); //4. 如果收到了byte直接结束循环 if("bye".equals(input)) {
break;
} } } }
启动服务端和客户端,然后再控制台输入一些测试数据,看一下服务端的控制台输出:
客户端输入数据
Hello UDP
服务端的输出数据
Client:-Hello UDP
好了Demo已经执行完了,非常简单。
3. UDP和TCP的区别有哪些?
1. TCP是可靠的传输,而UDP是非可靠数据传输。因为可靠,所以需要更高的延迟和网络带宽。而UDP则不需要,所以比较适合语音、视频电话等。
2. UDP的Header字节为8个字节,非常少,而TCP需要至少20个字节。
3. TCP是全双工的,即可以发送接收数据,可以想象两个人打电话,即可以听到声音又可以发送声音。而UDP发送数据的时候才连接,发送完数据之后不会保留连接。
4. TCP是点对点连接的,而UDP是多对多进行数据传输。TCP以字节流形式发送,有拥塞控制,方式发送数据量太大拥塞。而UDP是以报文形式发送给目标机器,没有拥塞控制。
4. TCP建连和关闭的过程,为什么建立连接的时候是三次握手,断开连接的时候需要四次?
1)三次握手建立连接处理:
1. 首先创建连接时client需要发送一个SYN+随机sequence给 server 端,这是客户端的状态是SYN_SENT状态。
2. server收到数据后会回复一个SYN+ACK,ACK为接收到的sequence+1,同时再发送一个sequence。server的状态为ACK_REVD。
3. client再把收到的sequnce+1作为ACK再给到服务端,然后服务端和客户端的状态都是ESTABLISHED。说明连接建立了。
第二步中的SYN和ACK可以同时发送,这两个值同时发送不受影响,都可以建立连接。当然如果两步分开发送也是可以的,但是由于可以节省一步发送,所以不用多费事。
2)四次握手关闭连接处理:
1. client发一个FIN和一个随机的sequence给server,然后客户端的状态变为FIN_WAIT_1状态。
2. server收到了FIN后,状态变为CLOSE_WAIT,然后再把接收到的sequence+1和ACK标志返回给client。client收到ACK后变为FIN_WAIT2状态。
3. 然后server再次给client发送一个FIN+sequence给client,此时客户端的状态变为TIME_WAIT状态。
4. client再把收到的sequence + 1发送给server, 此时server的状态变为CLOSED。此时连接正式断开。
这是客户端主动发起关闭连接的过程,还有同时发送FIN标志的情况。
1. client发送FIN+sequence给server端,状态变为FIN_WAIT_1。
2. server也发送FIN+sequence给client端,此时server的状态变为FIN_WAIT_1。client的接收FIN后变为CLOSING,同时server也变为CLOSING。
3. client发送ACK+接收到的sequence+1给server。client的状态变为TIME_WAIT。
4. server同时也发送ACK+接收到的seqnce+1给client。此时client和server都变为CLOSED。
整个过程是这么一个过程,那么为什么TCP连接的时候需要三次,而关闭的时候需要四次?
因为建立连接的时候SYN+ACK可以同时发送,不影响连接建立。而关闭的时候FIN+ACK不能合起来,因为TCP是双向且全双工连接。也就是client和server建立好连接后,client和server即能发送信息同时也能接收信息。当client发送FIN给server的时候,只能说明客户端不给server发送数据了,但是不证明client不接收数据,所以给到server后,server处理好之后说我也不给你发数据了(FIN)。然后我已经你不给我发数据了(ACK),这个时候client收到后说知道了(ACK), 此时连接就关闭了。
好了,关于这篇就整理到这里,如果有不对的地方欢迎批评指正。
聊聊UDP、TCP和实现一个简单的JAVA UDP小Demo的更多相关文章
- 一个简单的Java web服务器实现
前言 一个简单的Java web服务器实现,比较简单,基于java.net.Socket和java.net.ServerSocket实现: 程序执行步骤 创建一个ServerSocket对象: 调用S ...
- Java学习笔记 11/15:一个简单的JAVA例子
首先来看一个简单的 Java 程序. 来看下面这个程序,试试看是否看得出它是在做哪些事情! 范例:TestJava.java // TestJava.java,java 的简单范例 public ...
- Java入门篇(一)——如何编写一个简单的Java程序
最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中. 主要内容包括JavaSE.JavaEE的基础知识以及如何 ...
- 如何使用AEditor制作一个简单的H5交互页demo
转载自:http://www.alloyteam.com/2015/06/h5-jiao-hu-ye-bian-ji-qi-aeditor-jie-shao/ 本教程演示如何使用AEditor制作一个 ...
- 一个简单的MariaDB认证插件demo
代码地址如下:http://www.demodashi.com/demo/13076.html 一.前言 众所周知(其实可能很多人不知道)MariaDB支持插件认证.在MariaDB中新建用户,常见的 ...
- Ant—使用Ant构建一个简单的Java工程(两)
博客<Ant-使用Ant构建一个简单的Java项目(一)>演示了使用Ant工具构建简单的Java项目,接着这个样例来进一步学习Ant: 上面样例须要运行多条ant命令才干运行Test类中的 ...
- IntelliJ IDEA创建一个简单的Java Project(二)
1. 选择要创建的项目类型,同时配置本地的JDK 2. 是否使用模板创建项目 3. 选择项目在本地的存储位置 4. 点击Finish,完成一个简单的Java工程的创建.
- 利用 Docker 构建一个简单的 java 开发编译环境
目前 Java 语言的版本很多,除了常用的 Java 8,有一些遗留项目可能使用了 Java 7,也可能有一些比较新的的项目使用了 Java 10 以上的版本.如果想切换自己本地的 Java 开发环境 ...
- 【Java】一个简单的Java应用程序
简单记录,Java 核心技术卷I 基础知识(原书第10 版) 一个简单的Java应用程序"Hello, World!" Hello, World! Goodbye,World! 一 ...
随机推荐
- 【Linux网络基础】上网原理流程
1. 局域网用户上网原理 上网过程说明: 确保物理设备和线路架构准备完毕,并且线路通讯状态良好 终端设备需要获取或配置上局域网(私有地址)地址,作为局域网网络标识 当终端设备想上网时,首先确认访问的地 ...
- 4.pickling 和unpickling是什么?
pickling 和unpickling是什么? Pickle module accepts any Python object and converts it into a string repre ...
- ES6特性之:参数默认值
作为一个开发者,跟进行业步伐是非常需要的,不能躺在现有的知识和经验温床上做美梦.JavaScript的ES2015标准(即我们说的ES6)在2016年已经被广泛应用了,还没开始使用的朋友,赶紧来磨一下 ...
- The 2019 Asia Nanchang First Round Online Programming Contest B Fire-Fighting Hero(阅读理解)
This is an era of team success, but also an era of heroes. Throughout the ages, there have been nume ...
- python(类多态)
一.多态 (以封装和继承为前提)不同的子类调用相同的方法,产生不同的结果 class Dog(): def __init__(self,name): self.name = name def game ...
- 能量项链(区间DP入门)
题面:能量项链https://www.luogu.com.cn/problem/P1063 乍一看和石子合并差不多,可是多了头值和尾值,看起来十分麻烦 我们画一张图,紫色表示头值,蓝色表示尾值.规定西 ...
- spring的bean的属性注入
一.设置注入 设置注入要求: 要求属性在实体类中必须有getter 和setter方法,然后在spring的工厂中就可以使用property标签进行设值注入. 二.构造注入 通过类的构造方法的方式注入 ...
- node常用插件使用
1.nodemon 用于热更新,随时监控文件的变化 安装npm i -g nodemon 使用nodemon index.js 2.nvm nvm用于nodejs版本管理,我们在开发过程中,不同的项目 ...
- 今天主要做的是Remember Me(记住我)功能的实现
功能就是让网站登录过的人只要不注销,下次打开网站之后直接进入,不用重复登录,此功能主要是session与cookie的配合运用,具体实现是这样的,在登录页面判断并完成登录,然后将所需数据写入sessi ...
- web概念简述,HTML学习笔记
今日内容 1. web概念概述 2. HTML web概念概述 * JavaWeb: * 使用Java语言开发基于互联网的项目 * 软件架构: 1. C/S: Client/Server 客户端/服务 ...