TCP与UDP通信协议及Java实现

简介: 概述TCP (Transmission Control Protocol):传输控制协议 UDP(User Datagram Protocol):用户数据报协议TCP 与 UDP 都是 运输层(Transport Layer)上的因特网协议,运输层协议的功能就是为运行在不同主机上的应用进程之间提供 逻辑通信 ,使得运行不同进程的主机即使分隔于地球两侧,也能像是直接相连一样。

概述

TCP (Transmission Control Protocol):传输控制协议
UDP(User Datagram Protocol):用户数据报协议

TCP 与 UDP 都是 运输层(Transport Layer)上的因特网协议,运输层协议的功能就是为运行在不同主机上的应用进程之间提供 逻辑通信 ,使得运行不同进程的主机即使分隔于地球两侧,也能像是直接相连一样。
而具体做法是,它为来自应用层的报文添加上运输层首部来创建运输层报文段,这个首部中包含了以下信息
这里写图片描述
通过这些首部字段,不同主机之间的进程就可以通信了

UDP 为调用它的应用程序提供了一种 不可靠的 无连接 服务
TCP 为调用它的应用程序提供了一种 可靠的 面向连接 服务

UDP

UDP 可以说是一种极简的运输层协议,它的功能仅仅包括运输层必备的功能,即:多路复用/多路分解,差错检测
在后面的讲解中我们会知道 TCP 进行通信时,发送方与接收方先要进行“三次握手”来确认连接,而 UDP 则没有这一流程,所以说 UDP 是无连接
在 TCP 中,如果消息没有成功发送,发送方是会收到发送失败的反馈的,而 UDP 中,发送方发出数据后无法确认是否成功发送,只能靠接收方是否回复信息来确认上一次发送成功与否,因此在应用 UDP 时,通常会加入一个延时,如果超过额定时间未收到回复,就重新发送
DNS(Domain Name System,域名系统)就是一个应用 UDP 的例子,当我们输入网址访问网站时,DNS 就是通过 UDP 发送域名查询报文的。所以,如果长时间没有得到回复,我们就会看到“连接超时”的错误页面。
这里写图片描述
UDP 检验和,就是用来做差错检验的数据。
方法实现是,发送方的 UDP 对报文段中的所有 16 比特字的和进行反码运算,求和时遇到溢出要回卷。
例:有 3 个 16 比特字
0110 0110 0110 0000
0101 0101 0101 0101
1000 1111 0000 1100
①:前两个相加
0110 0110 0110 0000
0101 0101 0101 0101
————————————
1011 1011 1011 0101
②:和与第三个相加
1011 1011 1011 0101
1000 1111 0000 1100
————————————
(1)0100 1010 1100 0001
③:有溢出,进行回卷
0100 1010 1100 0001 + 1 = 0100 1010 1100 0010
④:转为反码,存入检验和
1011 0101 0011 1101
接收端收到数据后,会再次将数据取和,再与检验和相加,若结果为1111 1111 1111 1111则表示无差错,若出现 0 则表示有差错

UDP 虽然提供差错检测,但是不会进行错误修复,它要么直接丢弃错误段,要么将错误段上报应用程序

看到这里,不由得会产生一个疑问:UDP 这么的精简,功能不够强大,为什么还要用它呢?
原因是:

  1. 应用层能更好的控制要发送的数据和发送时间,实时性
  2. 无需建立连接,反应迅速
  3. 无连接状态,不需要维护连接状态,节省资源
  4. 分组首部开销小,节省数据段空间


TCP

应用 TCP 时,一个应用进程可以开始向另一个应用进程发送数据之前,这两个进程必须先进行“握手”,所以说,TCP 是面向连接的
TCP 连接提供的是 点对点,全双工服务
TCP 提供的是 可靠数据传输
TCP 通过使用 流量控制、序号、确认和定时器 等技术,确保正确地、按序地将数据从发送进程交付给接收进程
TCP 还提供了 拥塞控制 ,它允许 TCP 连接通过一条拥塞的网络链路,平等地共享网络链路带宽。

TCP 建立连接有三次握手
这里写图片描述

终止连接有四次握手

这里写图片描述

TCP 报文段结构
这里写图片描述


代码示例

UDP

UDPClient.java

package test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/** 
 * UDPCLient deom
 * @author <dht925nerd@126.com>
 */
public class UDPClient {
    public static void main(String[] args) throws Exception {
        DatagramSocket clientSocket = new DatagramSocket();
        BufferedReader inFromUser =
                new BufferedReader(
                        new InputStreamReader(System.in)
                );
        //获取本地 IP 地址
        InetAddress IPAddress = InetAddress.getLocalHost();
        byte[] sendData;
        byte[] receiveData = new byte[1024];
        System.out.println("请输入一句英文,服务器会返回其大写形式(输入exit退出)");
        while (true) {
            String sentence = inFromUser.readLine();
            if (sentence.equals("exit")) break;
            sendData = sentence.getBytes();
            //创建发送数据报包,并标注源地址#,目的地址#
            DatagramPacket sendPacket =
                    new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
            //发送数据报包
            clientSocket.send(sendPacket);
            //创建接收数据报包
            DatagramPacket receivePacket =
                    new DatagramPacket(receiveData, receiveData.length);
            //接收服务器的数据报包
            clientSocket.receive(receivePacket);
            String modifiedSentence = new String(receivePacket.getData());
            System.out.println("FROM SERVER: " + modifiedSentence);
        }
        clientSocket.close();
    }
}

UDPServer.java

package test;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * UDPServer Demo
 * @author <dht925nerd@126.com>
 */
public class UDPServer {
    public static void main(String[] args) throws Exception {
        DatagramSocket serverSocket =
                new DatagramSocket(9876);
        byte[] sendData;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        while (true) {
            byte[] receiveData = new byte[1024];
            //创建接收数据报包
            DatagramPacket receivePacket =
                    new DatagramPacket(receiveData, receiveData.length);
            //接收客户端数据报包
            serverSocket.receive(receivePacket);
            String sentence = new String(receivePacket.getData());
            //获取客户端地址
            InetAddress IPAddress = receivePacket.getAddress();
            if (sentence != null) System.out.println(df.format(new Date()) + " from " + IPAddress + ": " + sentence );
            //获得客户端端口号
            int port = receivePacket.getPort();
            String capitalizedSentence = sentence.toUpperCase();
            sendData = capitalizedSentence.getBytes();
            DatagramPacket sendPacket =
                    new DatagramPacket(sendData, sendData.length, IPAddress, port);
            //向客户端发送数据报包
            serverSocket.send(sendPacket);
        }
    }
}

测试方法:
① 先编译运行UDPServer.java
② 再运行 UDPClient.java
③ 在UDPClient的控制板面输入字符串,回车
④ 在UDPClient 和 UDPServer 控制板面观察运行信息

运行信息:
客户端
这里写图片描述
服务器端
这里写图片描述

TCP

TCPClient.java

package test;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * TCPClient demo
 * @author <dht925nerd@126.com>
 */
public class TCPClient {
    public static void main(String[] args) throws Exception {
        String sentence;
        String modifiedSentence;
        System.out.println("请输入一个英文字符串,服务器将返回其大写形式(输入exit退出)");
        while (true) {
            BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
            //创建客户端 Socket 并指明需要连接的服务器端的主机名及端口号
            Socket clientSocket = new Socket("localhost", 6789);
            DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
            BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            sentence = inFromUser.readLine();
            if (sentence.equals("exit")) break;
            //向服务器发送数据
            outToServer.writeBytes(sentence + '\n');
            //接收服务器返回数据
            modifiedSentence = inFromServer.readLine();
            System.out.println("FROM SERVER: " + modifiedSentence);
            clientSocket.close();
        }
    }
}

TCPServer.java

package test;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * TCPServer demo
 * @author <dht925nerd@126.com>
 */
public class TCPServer {
    public static void main(String[] args) throws Exception {
        String clientSentence;
        String capitalizedSentence;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //创建服务器端 Socket 并指明端口号
        ServerSocket welcomeSocket = new ServerSocket(6789);
        while(true) {
            //接收客户端连接
            Socket connectionSocket = welcomeSocket.accept();
            BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
            //获取客户端传入的字符串
            clientSentence = inFromClient.readLine();
            if (clientSentence != null)
                System.out.println(df.format(new Date()) + " from " + connectionSocket.getInetAddress() + ": " + clientSentence );
            capitalizedSentence = clientSentence.toUpperCase() + '\n';
            //向客户端发送修改后的字符串
            outToClient.writeBytes(capitalizedSentence);
        }
    }
}

测试方法:同上

目录
相关文章
|
3天前
|
监控 网络协议 网络性能优化
不再困惑!一文搞懂TCP与UDP的所有区别
本文介绍网络基础中TCP与UDP的区别及其应用场景。TCP是面向连接、可靠传输的协议,适用于HTTP、FTP等需要保证数据完整性的场景;UDP是无连接、不可靠但速度快的协议,适合DNS、RIP等对实时性要求高的应用。文章通过对比两者在连接方式、可靠性、速度、流量控制和数据包大小等方面的差异,帮助读者理解其各自特点与适用场景。
|
13天前
|
存储 网络协议 安全
用于 syslog 收集的协议:TCP、UDP、RELP
系统日志是从Linux/Unix设备及网络设备生成的日志,可通过syslog服务器集中管理。日志传输支持UDP、TCP和RELP协议。UDP无连接且不可靠,不推荐使用;TCP可靠,常用于rsyslog和syslog-ng;RELP提供可靠传输和反向确认。集中管理日志有助于故障排除和安全审计,EventLog Analyzer等工具可自动收集、解析和分析日志。
|
28天前
|
网络协议 网络性能优化 数据处理
深入解析:TCP与UDP的核心技术差异
在网络通信的世界里,TCP(传输控制协议)和UDP(用户数据报协议)是两种核心的传输层协议,它们在确保数据传输的可靠性、效率和实时性方面扮演着不同的角色。本文将深入探讨这两种协议的技术差异,并探讨它们在不同应用场景下的适用性。
68 4
|
28天前
|
监控 网络协议 网络性能优化
网络通信的核心选择:TCP与UDP协议深度解析
在网络通信领域,TCP(传输控制协议)和UDP(用户数据报协议)是两种基础且截然不同的传输层协议。它们各自的特点和适用场景对于网络工程师和开发者来说至关重要。本文将深入探讨TCP和UDP的核心区别,并分析它们在实际应用中的选择依据。
56 3
|
1月前
|
网络协议 算法 网络性能优化
|
1月前
|
网络协议 SEO
TCP连接管理与UDP协议IP协议与ethernet协议
TCP、UDP、IP和Ethernet协议是网络通信的基石,各自负责不同的功能和层次。TCP通过三次握手和四次挥手实现可靠的连接管理,适用于需要数据完整性的场景;UDP提供不可靠的传输服务,适用于低延迟要求的实时通信;IP协议负责数据包的寻址和路由,是网络层的重要协议;Ethernet协议定义了局域网的数据帧传输方式,广泛应用于局域网设备之间的通信。理解这些协议的工作原理和应用场景,有助于设计和维护高效可靠的网络系统。
42 4
|
1月前
|
缓存 负载均衡 网络协议
面试:TCP、UDP如何解决丢包问题
TCP、UDP如何解决丢包问题。TCP:基于数据块传输/数据分片、对失序数据包重新排序以及去重、流量控制(滑动窗口)、拥塞控制、自主重传ARQ;UDP:程序执行后马上开始监听、控制报文大小、每个分割块的长度小于MTU
|
2月前
|
网络协议 前端开发 物联网
TCP和UDP区别?
本文首发于微信公众号“前端徐徐”,详细介绍了TCP和UDP两种传输层协议的核心概念、连接性和握手过程、数据传输和可靠性、延迟和效率、应用场景及头部开销。TCP面向连接、可靠、有序,适用于网页浏览、文件传输等;UDP无连接、低延迟、高效,适用于实时音视频传输、在线游戏等。
73 1
TCP和UDP区别?
|
2月前
|
Web App开发 缓存 网络协议
不为人知的网络编程(十八):UDP比TCP高效?还真不一定!
熟悉网络编程的(尤其搞实时音视频聊天技术的)同学们都有个约定俗成的主观论调,一提起UDP和TCP,马上想到的是UDP没有TCP可靠,但UDP肯定比TCP高效。说到UDP比TCP高效,理由是什么呢?事实真是这样吗?跟着本文咱们一探究竟!
72 10
|
2月前
|
网络协议 网络性能优化 C#
C# 一分钟浅谈:UDP 与 TCP 协议区别
【10月更文挑战第8天】在网络编程中,传输层协议的选择对应用程序的性能和可靠性至关重要。本文介绍了 TCP 和 UDP 两种常用协议的基础概念、区别及应用场景,并通过 C# 代码示例详细说明了如何处理常见的问题和易错点。TCP 适用于需要可靠传输和顺序保证的场景,而 UDP 适用于对延迟敏感且可以容忍一定数据丢失的实时应用。
52 1