TCP、UDP协议的应用、ServerSocket和Socket、DatagramSocket和DatagramPacket

news2025/3/20 21:00:34

DAY13.1 Java核心基础

TCP协议

TCP 协议是面向连接的运算层协议,比较复杂,应用程序在使用TCP协议之前必须建立连接,才能传输数据,数据传输完毕之后需要释放连接

就好比现实生活中的打电话,首先确保电话打通了才能进行通信,如果没有打通则阻塞,需要等待打通才能对话

TCP优缺点:

  • 优点:安全可靠,数据不会丢失,并且数据是按照先后顺序依次到达
  • 缺点:速度慢,效率低,常用于对于业务安全要求较高的场景

Java中如何使用 TCP 呢?

java中通过Socket类来建立TCP连接,使用这个类可以在服务端和客户端建立一个可靠的连接

Socket表示客户端,ServerSocket表示服务端

它们都在java.net包中

在服务端创建ServerSocket对象,通过对象的accept()方法可以接收到若干个表示客户端的Socket对象

ServerSocket

方法描述
public ServerSocket(int port)根据端口创建 ServerSocket 实例对象
public ServerSocket(int port,int backlog)根据端口和 backlog 创建 ServerSocket 对象
public ServerSocket(int port,int backlog,InetAddress address)根据端口、backlog、IP 创建 ServerSocket对象
public ServerSocket()创建没有绑定服务器的 ServerSocket 对象
public synchronized int getSoTimeout()获取 Sotimeout 的设置
public InetAddress getInetAddress()获取服务器的 IP 地址
public Socket accept()等待客户端请求,并返回 Socket 对象
public void close()关闭 ServerSocket
public boolean isClosed()返回 ServerSocket 的关闭状态
public void bind(SocketAddress address)将 ServerSocket 实例对象绑定到指定地址
public int getLocalPort()返回 ServerSocket 的端口

Socket

方法描述
public Socket(String host,int port)根据主机、端口创建 Socket 对象
public Socket(InetAddress host,int port)根据 IP、端口创建 Socket 对象
public Socket(String host,int port,InetAddress address,int localPort)根据主机、端口创建要连接的 Socket 对象并将其连接到指定的远程主机上的指定端口
public Socket(InetAddress host,int port,InetAddress address,int localPort)根据主机、端口创建要连接的 Socket 对象并将其连接到指定的远程主机上的指定端口
pubilc Socket()创建没有连接的 Socket 对象
public InputStream getInputStream()返回 Socket 的输入流
public synchronized void close()关闭 Socket
public boolean isClosed()返回 Socket 的关闭状态、

DataInputStream 的作用

读取基本数据类型:提供方法直接读取二进制数据为Java基本类型,例如:

  • int readInt():读取4字节为int。
  • double readDouble():读取8字节为double。
  • String readUTF():读取修改后的UTF-8编码字符串。

跨平台一致性:数据以**网络字节序(Big-Endian)**存储,确保不同平台间数据读写兼容。

DataOutputStream 的作用

写入基本数据类型:将Java基本类型转换为字节序列写入流中,例如:

  • void writeInt(int v):将int写入为4字节。
  • void writeDouble(double v):将double写入为8字节。
  • void writeUTF(String str):以修改后的UTF-8格式写入字符串。

数据序列化:常用于将数据结构(如对象的字段)转换为字节流,便于存储或网络传输。

服务端启动的时候可以接收多个客户端的信息

服务端:ServerSocket

public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket socket = null;
        OutputStream outputStream = null;
        InputStream inputStream = null;
        DataInputStream dataInputStream = null;
        DataOutputStream dataOutputStream = null;
        try {
            serverSocket = new ServerSocket(8080);
            System.out.println("------服务端------");
            System.out.println("已启动,等待接收客户端请求...");
            while (true){
                socket = serverSocket.accept();
                inputStream = socket.getInputStream();
                dataInputStream = new DataInputStream(inputStream);
                String request = dataInputStream.readUTF();
                System.out.println("接收到了客户端请求:" + request);
                outputStream = socket.getOutputStream();
                dataOutputStream = new DataOutputStream(outputStream);
                String response = "Hello World";
                dataOutputStream.writeUTF(response);
                System.out.println("给客户端做出响应:" + response);
            }
        } catch (Exception e){

        } finally {
            try {
                dataOutputStream.close();
                outputStream.close();
                dataInputStream.close();
                inputStream.close();
                socket.close();
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

核心就是通过while循环accept()接收客户端的连接,然后通过DataInputStream和DataOutputStream实现了接收和发送的业务

启动等待客户端连接…

image-20250317173719789

客户端:Socket

public class Client {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream outputStream = null;
        DataOutputStream dataOutputStream = null;
        InputStream inputStream = null;
        DataInputStream dataInputStream = null;
        try {
            socket = new Socket("127.0.0.1", 8080);
            System.out.println("------客户端------");
            String request = "你好!";
            System.out.println("客户端说:" + request);
            outputStream = socket.getOutputStream();
            dataOutputStream = new DataOutputStream(outputStream);
            dataOutputStream.writeUTF(request);
            inputStream = socket.getInputStream();
            dataInputStream = new DataInputStream(inputStream);
            String response = dataInputStream.readUTF();
            System.out.println("服务器的响应是:" + response);
        } catch (Exception e){

        } finally {
            try {
                inputStream.close();
                dataInputStream.close();
                dataOutputStream.close();
                outputStream.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

客户端接收到的消息:

image-20250317174101983

此时服务端的输出为:

image-20250317174050370

UDP协议

TCP 协议连接可以建立稳定可靠的连接,保证信息的完整性,但是它的缺点也很明显,先建立连接再进行操作的方式效率必然低下

实际开发应用中,有些场景不需要可靠的连接,而是需要效率很高的传输,但连接不可靠,容易数据丢失

TCP:打电话,需要建立连接

UDP(发送消息,不需要建立连接):

  • 效率高,速度快,不需要建立连接,直接发送即可
  • 连接不可靠,容易数据丢失,安全性不高

DatagramSocket和DatagramPacket

DatagramSocket (邮箱,等待接收消息):

方法描述
public DatagramSocket(int port)根据端口创建 DatagramSocket 实例对象
public void send(DatagramPacket p)发送数据报
public synchronized void receive(DatagramPacket p)接收数据报
public InetAddress getInetAddress()获取 DatagramSocket 对应的 InetAddress 对象
public boolean isConnected()判断是否连接到服务

DatagramPacket(信封:封装发送的消息以及发送的地址):

方法描述
public DatagramPacket(byte[] buff,int length,InetAddress address,int port)根据发送的数据、数据长度、IP、端口创建 DatagramPacket 对象
public synchronized byte[] getData()获取接收的数据
public synchronized int getLength()获取数据长度
public synchronized int getPort()获取发送数据的 Socket 端口
public synchronized SocketAddress getSocketAddress()获取发送数据的 Socket 信息

客户端A:

public class TerminalA {
    public static void main(String[] args) {
        // 创建信箱
        try {
            byte[] buff= new byte[1024];
            SocketAddress socketAddress =new InetSocketAddress("127.0.0.1",8081);
            DatagramPacket datagramPacket= new DatagramPacket(buff,buff.length,socketAddress);
            DatagramSocket datagramSocket =new DatagramSocket(8080);
            // 等待接收8081信箱的消息
            System.out.println("客户端A等待接收消息....");
            datagramSocket.receive(datagramPacket);
            // 接收消息
            String msg = new String(datagramPacket.getData(),0,datagramPacket.getLength());
            System.out.println("接收到来自"+datagramPacket.getAddress()+":"+datagramPacket.getPort()+"端口的消息:"+msg);
            // 发送消息
            String s = "你好我是客户端A";
            byte[] bytes = s.getBytes();
            DatagramPacket datagramPacket1 =new DatagramPacket(bytes,bytes.length,new InetSocketAddress("127.0.0.1",8081));
            datagramSocket.send(datagramPacket1);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

image-20250318114800461

如果没有消息则一直阻塞等待

阻塞发生在 datagramSocket.receive(datagramPacket);

客户端 B:

public class TerminalB {
    public static void main(String[] args) {
        try {
            // 创建信箱
            DatagramSocket datagramSocket =new DatagramSocket(8081);
            // 发送消息给8080
            String s = "你好我是客户端B";
            byte[] bytes = s.getBytes();
            DatagramPacket datagramPacket1 =new DatagramPacket(bytes,bytes.length,new InetSocketAddress("127.0.0.1",8080));
            datagramSocket.send(datagramPacket1);

            // 接收消息
            SocketAddress socketAddress =new InetSocketAddress("127.0.0.1",8080);
            byte[] buff= new byte[1024];
            DatagramPacket datagramPacket= new DatagramPacket(buff,buff.length,socketAddress);
            // 等待接收8080信箱的消息
            System.out.println("客户端B等待接收消息....");
            datagramSocket.receive(datagramPacket);
            String msg = new String(datagramPacket.getData(),0,datagramPacket.getLength());
            System.out.println("接收到来自"+datagramPacket.getAddress()+":"+datagramPacket.getPort()+"端口的消息:"+msg);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

发送消息给A,A给B回信

image-20250318114859741

image-20250318114847927

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2318580.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

配置VMware Workstation中Ubuntu虚拟机与Windows主机的剪贴板共享功能

步骤1:安装或更新VMware Tools组件‌ ‌卸载旧版本工具(可选)‌ 若已安装旧版工具,建议先卸载: sudo apt-get autoremove open-vm-tools‌安装必需组件‌ sudo apt-get updatesudo apt-get install open-vm-tools o…

深入理解Python闭包与递归:原理、应用与实践

目录 闭包 什么是闭包: 闭包的基本结构: 实现闭包的条件: 1.嵌套函数 2.内函数引用外部函数的变量 3.外部函数返回内部函数 4.外部函数已经执行完毕 递归函数 什么是递归函数: 递归函数条件 1.必须有个明确的结束条…

SeaCMS代码审计

漏洞描述 漏洞分析 根据漏洞描述定位漏洞代码 当actionsaveCus或者save时,可以进行一个文件写入,不过文件类型被进行了限制,只有html,htm,js,txt,css 虽然这里并不能写入php文件,但是当actionadd或者custom时,这里进行…

好看的网络安全登录页面 vue http网络安全

一、http协议 http协议是一种网络传输协议,规定了浏览器和服务器之间的通信方式。位于网络模型中的应用层。(盗图小灰。ヾ(◍∇◍)ノ゙) 但是,它的信息传输全部是以明文方式,不够安全,…

Unity--GPT-SoVITS接入、处理GPTAPI的SSE响应流

GPT-SoVITS GPT-SoVITS- v2(v3也可以,两者对模型文件具有兼容) 点击后 会进入新的游览器网页 ----- 看了一圈,发现主要问题集中在模型的训练很需要CPU,也就是模型的制作上,问题很多,如果有现有…

Redis哈希槽机制的实现

Redis哈希槽机制的实现 Redis集群使用哈希槽(Hash Slot)来管理数据分布,整个集群被划分为固定的16384个哈希槽。当我们在集群中存储一个键时,Redis会先对键进行哈希运算,得到一个哈希值。然后,Redis将该哈…

docker pull 提示timeout

通过命令行拉取对应的mysql版本提示网络超时。 开始排查,首先确认是否能浏览器访问。ok的,可以正常访问。 终端curl 排查嗯 有问题 改了下 终端 vim ~/.zshrc 加入 export HTTP_PROXY"http://127.0.0.1:7890" export HTTPS_PROXY"…

(超详细) ETL工具之Kettle

Kettle简介 kettle最早是一个开源的ETL工具,后命名为Pentaho Data Integration。由JAVA开发,支持跨平台运行,其特性包括:支持100%无编码、拖拽方式开发ETL数据管道,可对接包括传统数据库、文件、大数据平台、接口、流…

random_masking 函数测试

文章目录 1. description2. excel3. pytorch code 1. description 功能:按一定比例的随机部分样本,简单来说就是按照一定的比例将行向量从小到大的顺序提取出来。思考1: 用了均匀分布,并且按照一定比例,取前prob概率来…

TDengine 中的流式计算

简介 TDengine 中的流计算,功能相当于简化版的 FLINK , 具有实时计算,计算结果可以输出到超级表中存储,同时也可用于窗口预计算,加快查询速度。 创建流式计算 CREATE STREAM [IF NOT EXISTS] stream_name [stream_o…

Java 大视界 -- Java 大数据在智慧交通自动驾驶仿真与测试数据处理中的应用(136)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

JVM的一些知识

JVM简介 JVM 是 Java Virtual Machine 的简称,意为 Java 虚拟机。 虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。常见的虚拟机:JVM、VMwave、Virtual Box。 JVM 和其他两个虚拟机的区别: VMw…

C语言每日一练——day_7

引言 针对初学者,每日练习几个题,快速上手C语言。第七天。(连续更新中) 采用在线OJ的形式 什么是在线OJ? 在线判题系统(英语:Online Judge,缩写OJ)是一种在编程竞赛中用…

Java使用FFmpegFrameGrabber进行视频拆帧,结合Thumbnails压缩图片保存到文件夹

引入依赖 <dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.17</version></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ja…

用hexo初始化博客执行hexo init时碰到的问题

用hexo初始化博客执行hexo init时碰到的问题 $ hexo init myblog INFO Cloning hexo-starter https://github.com/hexojs/hexo-starter.git fatal: unable to access https://github.com/hexojs/hexo-starter.git/: SSL certificate problem: unable to get local issuer cer…

4.1--入门知识扫盲,ISO知识体系介绍(看一遍,协议啥的全部记住)

OSI七层模型&#xff1a;网络世界的"七重天"生存指南&#xff08;附快递小哥版图解&#xff09; “如果你觉得网络分层很抽象&#xff0c;那就想象自己在寄快递” —— 来自一个被三次握手逼疯的程序员 开场白&#xff1a;网络通信就像送外卖 假设你要给隔壁妹子送奶…

AI训练如何获取海量数据,论平台的重要性

引言&#xff1a;数据——AI时代的“新石油” 在人工智能和大模型技术飞速发展的今天&#xff0c;数据已成为驱动技术进步的 “ 燃料 ”。无论是训练聊天机器人、优化推荐算法&#xff0c;还是开发自动驾驶系统&#xff0c;都需要海量、多样化的数据支持。 然而&#xff0c;获…

Git 使用SSH登陆

一、SSH介绍 SSH连接相比于HTTP连接会简单一点&#xff0c;因为SSH连接通过了私钥与公钥进行身份认证&#xff0c;这样就不需要像HTTP一样&#xff0c;每次clone或者操作仓库都需要输入密码 其中私钥和密钥是需要在自己电脑上生成的&#xff0c;通过命令即可生成一个私钥和一个…

织梦DedeCMS修改文章【标题、短标题、关键词】长度限制

在后台虽然可以设置标题的长度&#xff0c;但是数据库的字段固定是60个字符&#xff0c;短标题是36字符&#xff0c;关键词30字符&#xff0c;所以这里教大家修改一下织梦DedeCMS修改【标题】【短标题】【关键词】长度限制 一、后台配置 1、进入dede后台管理 -> 系统 ->…

Powershell WSL部署ubuntu22.04.5子系统

前提条件WSL 安装 wsl 安装参考1wsl 安装csdn参考2wsl 百度网盘离线下载 本地目录安装ubuntu22.04.5 子系统 powershell 管理员打开执行(实现,下载安装ubuntu子系统,用户创建,远程ssh登录设置,防火墙端口开放)子系统IP 查看方法wsl