Java网络通信UDP

news/2024/5/18 12:35:58 标签: udp, 网络协议, 网络

目录

网络通信基础

UDP通信

服务器

1.想要使用UDP通信 要先打开DatagramSocket文件 端口号可以手动指定或系统随机分配

2.阻塞等待接收客户端数据;创建DatagramPacket接收客户端传来的数据

3.处理客户端传来的数据,并进行业务处理(这里只演示UDP通信 所以只是回传数据)

4.处理数据成DatagramPacket并发送数据给客户端

整体代码

客户端

1.创建DatagramSocket (这里客户端端口号系统分配即可,不允许和服务器同一端口号)

2.客户端接收用户的数据

3.处理用户数据成DatagramPacket 指定要发送服务器的地址与端口号

4.发送数据给客户端

5.阻塞等待服务器响应

6.处理服务器响应的数据

7.显示数据给用户

整体代码

继承服务器代码,重写业务代码即可


网络通信基础

  1. 物理层:网络通信的基础设施                                    运快递的公路
  2. 数据链路层:两个相邻的节点之间如何传输               两个集散点之间的传输
  3. 网络层:两个点之间的路径规划                                 物流公司规划快递的路径
  4. 传输层:两个点之间的通信(不考虑路径规划)        卖家发货 只考虑起点和终点
  5. 应用层:数据传输过去之后 如何使用                         快递拿到之后如何使用

网络编程的主要工作写应用层的代码,处理应用层的协议数据

从5->1往下传输 每次传输都会依次添加报头 称为封装    QQ1发送

从1->5往上传输 每次传输都会解析去掉报头                   QQ2接收

传输层提供两种协议

TCP:有连接,可靠传输,面向字节流,全双工

UDP:无连接,不可靠传输,面向数据包,半双工

可靠传输:数据对方有没有接收到,发送方有感知;打电话就是可靠的,可以知道对方有没有听到。

不可靠传输:数据对方有没有接收到,不管,也不知道;微信就是不可靠,不知道对方有没有看到我的消息。

全双工:双向通信 可以A->B B->A 同时进行

半双工:单向通信 A->B或者B->A 同时只允许一个进行

程序要进行网络通信,需要一个端口号(客户端与服务器的端口号不能相同!)

端口号相当于用来在网络上区分进行的身份标识符

分配端口号有 1.手动指定 2.系统自动分配

UDP通信

UDP的Socket API

DatagramSocket和DatagramPaclet 核心类

socket类本质相当于文件 构造一个DatagramSock对象,相当于打开了一个内核中的socket文件

打开后就可以传输数据了

传输数据已 DatagramPacket为基本单位

InetSocketAddress类 IP地址+端口号

send发送数据 receive接收数据 close关闭数据

DatagramOacket 表示一个UDP数据报 UDP是面向数据报的协议

服务器

1.想要使用UDP通信 要先打开DatagramSocket文件 端口号可以手动指定或系统随机分配

    //想要使用UDP服务器 要打开一个文件
    private DatagramSocket socket=null;

    //创建对象
    //服务器IP和端口号是提供给客户端 方便客户端知道地址发送过来
    public Test1(int port) throws SocketException {
        socket=new DatagramSocket(port);//创建实例  绑定进程端口号

2.阻塞等待接收客户端数据;创建DatagramPacket接收客户端传来的数据

            DatagramPacket datagramPacket=new DatagramPacket(new byte[4096],4096);
            //客户端发来的请求放到参数datagramPacket  输出性参数
            System.out.println("我正在等待!");
            socket.receive(datagramPacket);//阻塞等待 客户端发起请求
            System.out.println("服务器接收到数据");

3.处理客户端传来的数据,并进行业务处理(这里只演示UDP通信 所以只是回传数据)

//把传来的数据构造成数据 1.获取数据 从0开始构造 构造到数据结尾
            String request=new String(datagramPacket.getData(),0,datagramPacket.getLength());
            System.out.println("接收到的数据:"+request);
            //处理业务
            String requst=process(request);
            System.out.println("服务器处理数据");

 public String process(String s){
        return s;
    }

4.处理数据成DatagramPacket并发送数据给客户端

//要传回客户端也要把数据构造成DatagramPacket
            //把string构造到byte字节  1.字节数据,2.字节长度 3.客户端的id+客户端的端口号
            DatagramPacket datagramPackets=new DatagramPacket(request.getBytes(),request.getBytes().length,datagramPacket.getSocketAddress());
            //发送数据
            socket.send(datagramPackets);
            System.out.println("服务器发送数据成功");
            System.out.printf("[地址:%s:端口号:%d] 发来数据:%s 服务器响应数据:%s\n",datagramPacket.getAddress().toString(),datagramPacket.getPort(),request,requst);

整体代码

package DemoUDP;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

//服务端
public class Test1 {
    //想要使用UDP服务器 要打开一个文件
    private DatagramSocket socket=null;

    //创建对象
    //服务器IP和端口号是提供给客户端 方便客户端知道地址发送过来
    public Test1(int port) throws SocketException {
        socket=new DatagramSocket(port);//创建实例  绑定进程端口号
    }

    public void start() throws IOException {
        System.out.println("启动服务器");
        while (true){
            //创建一个DatagramPacket(创建缓存区,缓存区长度)用来接收客户端发来的请求
            DatagramPacket datagramPacket=new DatagramPacket(new byte[4096],4096);
            //客户端发来的请求放到参数datagramPacket  输出性参数
            System.out.println("我正在等待!");
            socket.receive(datagramPacket);//阻塞等待 客户端发起请求
            System.out.println("服务器接收到数据");
            //把传来的数据构造成数据 1.获取数据 从0开始构造 构造到数据结尾
            String request=new String(datagramPacket.getData(),0,datagramPacket.getLength());
            System.out.println("接收到的数据:"+request);
            //处理业务
            String requst=process(request);
            System.out.println("服务器处理数据");

            //要传回客户端也要把数据构造成DatagramPacket
            //把string构造到byte字节  1.字节数据,2.字节长度 3.客户端的id+客户端的端口号
            DatagramPacket datagramPackets=new DatagramPacket(request.getBytes(),request.getBytes().length,datagramPacket.getSocketAddress());
            //发送数据
            socket.send(datagramPackets);
            System.out.println("服务器发送数据成功");
            System.out.printf("[地址:%s:端口号:%d] 发来数据:%s 服务器响应数据:%s\n",datagramPacket.getAddress().toString(),datagramPacket.getPort(),request,requst);
        }
    }
    public String process(String s){
        return s;
    }

    public static void main(String[] args) throws IOException {
        //端口号范围 0--65535 1024以下的端口是系统用的  尽量用1024以上 65535以下
        Test1 test1=new Test1(8080);
        test1.start();
    }
}

客户端

1.创建DatagramSocket (这里客户端端口号系统分配即可,不允许和服务器同一端口号)

DatagramSocket Socket=null;

    //客户端端口号需要系统自动分配 不能指定与服务器端口号一样,不然会抢占服务器端口号 导致后启动的一端无法启动
    public Test2() throws SocketException {
        Socket=new DatagramSocket();
    }

2.客户端接收用户的数据

Scanner scanner=new Scanner(System.in);
            System.out.println("客户端输入数据:>");
            String Data=scanner.nextLine();

3.处理用户数据成DatagramPacket 指定要发送服务器的地址与端口号

//处理用户数据
            //1.把string类型处理成byte字节数据 datagramPacket类型 里面附带发送地址和发送对方的端口号
            DatagramPacket datagramPacket=new DatagramPacket(Data.getBytes(),Data.getBytes().length, InetAddress.getByName("127.0.0.1"),8080);
            System.out.println("客户端处理数据");

4.发送数据给客户端

 //发送数据
            Socket.send(datagramPacket);
            System.out.println("客户端发送数据");

5.阻塞等待服务器响应

//阻塞等待服务器的响应数据
            DatagramPacket datagramPackets=new DatagramPacket(new byte[1024],1024);
            Socket.receive(datagramPackets);
            System.out.println("客户端接收服务器响应数据");

6.处理服务器响应的数据

//处理服务器响应的数据
            String Datas=new String(datagramPackets.getData(),0,datagramPackets.getLength());
            System.out.println("客户端处理数据");

7.显示数据给用户

System.out.printf("服务器响应数据:%s\n",Datas);

整体代码

package DemoUDP;

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

//客户端
public class Test2 {
    DatagramSocket Socket=null;

    //客户端端口号需要系统自动分配 不能指定与服务器端口号一样,不然会抢占服务器端口号 导致后启动的一端无法启动
    public Test2() throws SocketException {
        Socket=new DatagramSocket();
    }

    public void start() throws IOException {
        while (true){
            //接收用户数据
            Scanner scanner=new Scanner(System.in);
            System.out.println("客户端输入数据:>");
            String Data=scanner.nextLine();

            //处理用户数据
            //1.把string类型处理成byte字节数据 datagramPacket类型 里面附带发送地址和发送对方的端口号
            DatagramPacket datagramPacket=new DatagramPacket(Data.getBytes(),Data.getBytes().length, InetAddress.getByName("127.0.0.1"),8080);
            System.out.println("客户端处理数据");

            //发送数据
            Socket.send(datagramPacket);
            System.out.println("客户端发送数据");

            //阻塞等待服务器的响应数据
            DatagramPacket datagramPackets=new DatagramPacket(new byte[1024],1024);
            Socket.receive(datagramPackets);
            System.out.println("客户端接收服务器响应数据");

            //处理服务器响应的数据
            String Datas=new String(datagramPackets.getData(),0,datagramPackets.getLength());
            System.out.println("客户端处理数据");

            //显示处理后的数据给用户
            System.out.printf("服务器响应数据:%s\n",Datas);
        }
    }

    public static void main(String[] args) throws IOException {
        Test2 test2=new Test2();
        test2.start();
    }
}

继承服务器代码,重写业务代码即可

package DemoUDP;

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;

public class Test3 extends Test1{

    public Test3(int port) throws SocketException {
        super(port);
    }

    @Override
    public String process(String s) {
        Map<String,String> dic=new HashMap<String,String>();

        dic.put("cat","猫");

        return dic.getOrDefault(s,"此单词还未更新");
    }

    public static void main(String[] args) throws IOException {
        Test3 test3=new Test3(8080);
        test3.start();
    }


}

指定客户端多开

之后就可以同时运行多个客户端访问服务器


http://www.niftyadmin.cn/n/5404963.html

相关文章

基于R语言的分位数回归技术应用

回归是科研中最常见的统计学研究方法之一&#xff0c;在研究变量间关系方面有着极其广泛的应用。由于其基本假设的限制&#xff0c;包括线性回归及广义线性回归在内的各种常见的回归方法都有三个重大缺陷&#xff1a;(1)对于异常值非常敏感&#xff0c;极少量的异常值可能导致结…

第十四届蓝桥杯大赛B组 JAVA 蜗牛 (递归剪枝)

题目描述&#xff1a; 这天&#xff0c;一只蜗牛来到了二维坐标系的原点。 在 x 轴上长有 n 根竹竿。它们平行于 y 轴&#xff0c;底部纵坐标为 0&#xff0c;横坐标分别为 x1, x2, …, xn。竹竿的高度均为无限高&#xff0c;宽度可忽略。蜗牛想要从原点走到第 n 个竹竿的底部也…

【小程序】媒体API能力集成指南——视频、原生视频、WebView、相机API

视频 API createVideoContext ty.createVideoContext(string id) 创建 video 上下文 VideoContext 对象。 参数 string id video 组件的 id 返回值 VideoContext VideoContext VideoContext 实例&#xff0c;可通过 ty.createVideoContext 获取。 VideoContext 通过…

分布式ID生成系统之雪花算法详解

在当今的云计算和微服务架构盛行的时代&#xff0c;分布式系统已成为软件开发的重要组成部分。随着系统规模的扩大和业务的复杂化&#xff0c;对数据一致性和唯一性的要求也越来越高&#xff0c;尤其是在全局唯一标识符&#xff08;ID&#xff09;的生成上。因此&#xff0c;分…

华为配置攻击检测功能示例

配置攻击检测功能示例 组网图形 图1 配置攻击检测功能示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响用户的业务使用。…

【算法大家庭】动态规划算法

目录 &#x1f9c2;1.动态规划思想 &#x1f32d;2.背包问题思路分析 &#x1f37f;3.代码实现 1.动态规划思想 将大问题划分为小问题进行解决&#xff0c;从而一步步获取最优解的处理算法适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的 2.背包问题思路分…

Vue3如何使用Pinia状态管理库与持久化

大家好&#xff0c;我是你们的好朋友咕噜铁蛋&#xff01;今天我将和大家分享如何在Vue3中使用Pinia状态管理库以及实现状态持久化的方法。作为一个Vue开发者&#xff0c;我们知道状态管理在大型应用程序中起着至关重要的作用。而Pinia作为Vue3推荐的状态管理库之一&#xff0c…

35 Spring整合Elasticsearch

文章目录 Spring整合Elasticsearch引入依赖配置Elasticsearch解决冲突 使用ElasticsearchSpring Data Elasticsearch建立映射关系常用方法添加数据修改数据删除数据搜索数据&#xff08;es核心&#xff09;步骤构造搜索条件 并 应用进行查询使用查询结果 Spring整合Elasticsear…