最近真的比较忙,很久就想写了,可是一直苦于写点什么,今天脑袋灵光一闪,觉得自己再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的更多相关文章

  1. 一个简单的Java web服务器实现

    前言 一个简单的Java web服务器实现,比较简单,基于java.net.Socket和java.net.ServerSocket实现: 程序执行步骤 创建一个ServerSocket对象: 调用S ...

  2. Java学习笔记 11/15:一个简单的JAVA例子

    首先来看一个简单的 Java 程序. 来看下面这个程序,试试看是否看得出它是在做哪些事情! 范例:TestJava.java   // TestJava.java,java 的简单范例  public ...

  3. Java入门篇(一)——如何编写一个简单的Java程序

    最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中. 主要内容包括JavaSE.JavaEE的基础知识以及如何 ...

  4. 如何使用AEditor制作一个简单的H5交互页demo

    转载自:http://www.alloyteam.com/2015/06/h5-jiao-hu-ye-bian-ji-qi-aeditor-jie-shao/ 本教程演示如何使用AEditor制作一个 ...

  5. 一个简单的MariaDB认证插件demo

    代码地址如下:http://www.demodashi.com/demo/13076.html 一.前言 众所周知(其实可能很多人不知道)MariaDB支持插件认证.在MariaDB中新建用户,常见的 ...

  6. Ant—使用Ant构建一个简单的Java工程(两)

    博客<Ant-使用Ant构建一个简单的Java项目(一)>演示了使用Ant工具构建简单的Java项目,接着这个样例来进一步学习Ant: 上面样例须要运行多条ant命令才干运行Test类中的 ...

  7. IntelliJ IDEA创建一个简单的Java Project(二)

    1.  选择要创建的项目类型,同时配置本地的JDK 2. 是否使用模板创建项目 3. 选择项目在本地的存储位置 4. 点击Finish,完成一个简单的Java工程的创建.

  8. 利用 Docker 构建一个简单的 java 开发编译环境

    目前 Java 语言的版本很多,除了常用的 Java 8,有一些遗留项目可能使用了 Java 7,也可能有一些比较新的的项目使用了 Java 10 以上的版本.如果想切换自己本地的 Java 开发环境 ...

  9. 【Java】一个简单的Java应用程序

    简单记录,Java 核心技术卷I 基础知识(原书第10 版) 一个简单的Java应用程序"Hello, World!" Hello, World! Goodbye,World! 一 ...

随机推荐

  1. Red 编程语言 2019 开发计划:全速前进!

    开发四年只会写业务代码,分布式高并发都不会还做程序员? >>>   Red 编程语言开发团队昨日发布了一篇 "Full steam ahead" 的文章,对其 2 ...

  2. 深入理解Mysql——锁、事务与并发控制

    本文对锁.事务.并发控制做一个总结,看了网上很多文章,描述非常不准确.如有与您观点不一致,欢迎有理有据的拍砖! mysql服务器逻辑架构 每个连接都会在mysql服务端产生一个线程(内部通过线程池管理 ...

  3. RHEL6 搭建 keepalived + lvs/DR 集群

    搭建 keepalived + lvs/DR  集群 使用Keepalived为LVS调度器提供高可用功能,防止调度器单点故障,为用户提供Web服务: LVS1调度器真实IP地址为192.168.4. ...

  4. Process Synchronization-Example 1

    问题描述 把学生和监考老师都看作进程,学生有N人,教师1人.考场门口每次只能进出一个人,进考场原则是先来先进.当N个学生都进入考场后,教师才能发卷子.学生交卷后可以离开考场,教师要等收上来全部卷子并封 ...

  5. BSGS 和扩展

    BSGS BSGS,全称叫 BabyStepGiantStep,也就是大步小步 其实还是比较暴力的 它可以\(O(\sqrt p)\)的复杂度内解出: \[a^x\equiv n\pmod p,\gc ...

  6. java基础知识备忘

    1.java内存分配 a.寄存器cup -- 暂不涉及 b.本地方法栈  -- 虚拟机调用windows功能用的,比如创建文件夹 c.方法区  -- 存放 .class文件,负责存放方法 d.栈 -- ...

  7. ASP.NET Core 如何使用Mvc相关技术建立Controller、Tag Helper (下)

    上篇文章介绍了通过定义两个接口和服务类,分别实现这两个接口,并且进行了一个服务的注册. 今天就来建立Controller 接下来就是在控制器中通过构造函数的方式注入接口(见代码块6行) 代码块2行的意 ...

  8. 学习Vue第一节,Vue的模式与写法格式

    引用Vue <script src="js/vue-2.4.0.js" type="text/javascript" charset="utf- ...

  9. 线段树 扫描线 L - Atlantis HDU - 1542 M - City Horizon POJ - 3277 N - Paint the Wall HDU - 1543

    学习博客推荐——线段树+扫描线(有关扫描线的理解) 我觉得要注意的几点 1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1] 2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个pu ...

  10. 流媒体与实时计算,Netflix公司Druid应用实践

    Netflix(Nasdaq NFLX),也就是网飞公司,成立于1997年,是一家在线影片[租赁]提供商,主要提供Netflix超大数量的[DVD]并免费递送,总部位于美国加利福尼亚州洛斯盖图.199 ...