Java UDP套接字编程:高效实时通信的实战应用与核心类解析

一、网络编程

什么是网络编程?

我们打开视频网站,比如腾讯视频,看仙逆,剑来等动漫,实质上是通过网络,获取到网络上的一个视频资源。

与在本地打开一个视频文件一样,只是这个视频文件来源于网络,相对于本地,网络提供了更为丰富的网络资源。

1.1、网络编程

网络编程是指通过编写程序来实现计算机之间的通信和数据交换。它涉及使用网络协议(如 TCP/IP、UDP等)在网络上发送和接收数据。(网络上的主机,通过不同的进程,以编码的方式实现网络通信)

即便是同一个主机,只要进程不同,基于网络来传输数据,也属于网络编程。

1.2、网络编程的核心概念

1.2.1、客户端和服务端

服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端。

客户端:获取服务的一方进程,称为客户端。

1.2.2、Socket套接字

概念:Socket套接字是由系统提供用于网络通信的基本操作单元

基于Socket套接字的网络程序开发就是网络编程。

主要分为以下三类:

(1)流套接字

使用传输层TCP协议

TCP(Transmission Control Protocol)传输控制协议

特点:

• 有连接

• 可靠传输

• 面向字节流

• 有接受缓存区,也有发送缓存区

• 大小不限

字节流:基于IO流以字节为单位进行数据传输,数据在流未关闭的情况下可以持续发送和接受.

(2)数据报套接字

使用传输层UDP协议

UDP(User Datagram Protocol)用户数据报协议

特点:

• 无连接

• 不可靠传输

• 面向数据报

• 有接受缓存区,无发送缓存区

• 大小受限:一次最多传输64K

数据报:传输是原子的,发送和接受操作必须一次性完成,发送方需将数据封装成一个数据报,接收方则接受整个数据报。

(3)原始套接字

**原始套接字(Raw Socket)**是一种允许应用程序直接访问网络层协议的套接字类型。与常见的流式套接字(如TCP)或数据报套接字(如UDP)不同,原始套接字允许用户自定义网络层协议头,甚至可以直接发送和接收原始数据包。(此知识我们不过多讲解)

1.3、数据报套接字通信模型

上文UDP,即用户数据报协议是无连接,面向数据报的特征,每次都是没有建立连接,并且一次性发送所有数据报,一次性接受所有数据报。

Java中使用UDP协议通信,主要是基于DatagramPacket 类来创建数据报套接字 ,并使用DatagramPacket作为发送或接受的UDP数据报,对于一次发送及接受UDP数据报的流程如下:

1.4、流套接字通信模型

TCP,即传输控制协议是有连接的,基于IO流,持续发送和接收的协议。

Java使用TCP协议通信,在服务端创建ServerSocket并绑定端口创建Socket连接ServerSocket对象接受客户端的Socket对象调用方法实现通信 ;在客户端创建Socket对象指定服务端地址和端口。

不论是客户端和服务端都要在通信完成后关闭流对象,服务端要多关闭一个Socket对象,客户端的Socket对象会随通信完成后进程的结束而自动关闭~~

流程如下 :

1.5、 Socket编程注意事项

(1)客户端和服务端:开发时,经常是基于一个主机开启两个进程作为客户端和服务端,但在真实情况下。一般都是不同主机。

(2)目的IP和端口号,标识了一次数据传输时要发送数据的终点主机和进程。

(3)Socekt编程是我们使用流套接字和数据报套接字,基于传输层的TCP或UDP协议,但在应用层协议,也需要考虑(后续更新)。

(4)端口占用,如果一个进程Q已经绑定了一个端口,在启动一个进程P绑定该端口,就会报错,报错信息如下:

我们可以在 cmd 中输入 netstat -ano | findstr 端口号,可以显示对应进程的 pid

然后在任务管理器 中,通过 pid查看进程 :

解决端口被占用的问题:

(1)如果占用端口的进程A不需要运行,就可以关闭A后,再启动需要绑定该端口的进程B.

(2)如果需要运行A进程,则可以修改进程B的绑定端口,换为其他没有使用的端口。

二、 UDP数据报套接字编程

2.1、API介绍

DatagramSocket(通信端点)

DatagramSocket是UDP Socket,用于发送和接收UDP数据报。

构造方法

DatagramSocket 方法

DatagramPacket(数据容器)

DatagramPacket是UDP Socket发送和接收UDP数据报

构造方法

DatagramPacket方法

InetSocketAaddress

InetSocketAaddress是(SocketAddress的子类)构造方法

2.2、模拟实现服务器

2.2.1、完整代码
java 复制代码
package UdpEcho;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.sql.PreparedStatement;

public class UdpEchoServer {
    private DatagramSocket datagramSocket=null;
    public UdpEchoServer(int port) throws SocketException {
        datagramSocket=new DatagramSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动!");
        while(true){
            DatagramPacket requestPacket=new DatagramPacket(new byte[4048],4048);
            datagramSocket.receive(requestPacket);
            String request=new String(requestPacket.getData(),0,requestPacket.getLength());
            String response=procsee(request);
            DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
            datagramSocket.send(responsePacket);
            System.out.printf("[%s:%d]   req:%s    rep:%s/n",
                    requestPacket.getAddress(),requestPacket.getPort(),request,response);
        }
    }
    public String procsee(String s){
        return s;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server=new UdpEchoServer(8776);
        server.start();
    }
}
2.2.2、核心组件
2.2.3、服务启动流程
2.2.4、与客户端交互流程图

2.3、模拟实现客户端

2.2.1、完整代码
java 复制代码
package UdpEcho;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UdpEchoClient {
    private String IP;
    private  int Port;
    private DatagramSocket socket=null;
    public UdpEchoClient(String ip,int port) throws SocketException {
        this.IP=ip;
        this.Port=port;
        socket=new DatagramSocket();
    }
    public void start() throws IOException {
        Scanner sc=new Scanner(System.in);
        while(true) {
            if (!sc.hasNext()){
                break;
            }
            System.out.println("请输入您要发送的内容:");
            String request=sc.next();
            DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(IP),Port);
            socket.send(requestPacket);
            DatagramPacket responsePacket=new DatagramPacket(new byte[4048],4048);
            socket.receive(responsePacket);
            String response=new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client=new UdpEchoClient("127.0.0.1",8776);
        client.start();
    }
}
2.2.2、核心组件

UDP是无连接的,故要定义IP和端口号,构造方法中Socket未指定本地端口号,由系统自动分配以避免冲突。

java 复制代码
    private String IP;
    private  int Port;
    private DatagramSocket socket=null;
    public UdpEchoClient(String ip,int port) throws SocketException {
        this.IP=ip;
        this.POrt=port;
        socket=new DatagramSocket();
    }
2.2.3、通信流程
java 复制代码
   public void start() throws IOException {
        Scanner sc=new Scanner(System.in);
        while(true) {
            if (!sc.hasNext()){
                break;
            }
            System.out.println("请输入您要发送的内容:");
            String request=sc.next();
            DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(IP),POrt);
            socket.send(requestPacket);
            DatagramPacket responsePacket=new DatagramPacket(new byte[4048],4048);
            socket.receive(responsePacket);
            String response=new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }
    }
2.2.4、与服务端交互流程
相关推荐
奋进的芋圆32 分钟前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin1 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20051 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉1 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国1 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882482 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈2 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_992 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹2 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理
专注_每天进步一点点2 小时前
【java开发】写接口文档的札记
java·开发语言