【网络编程】UDP实现回显服务器

一.网络编程的基本术语.

  • 客户端

客户端是为用户提供本地服务的程序,通常位于用户设备上。也称为用户端,是相对于服务器而言的。它主要指安装在用户设备上的程序,这些程序能够与服务器进行通信,从而获取服务或者执行特定功能。在互联网应用中,常见的客户端包括网页浏览器、电子邮件客户端和即时通讯软件等。它们需要与远端的服务器建立连接,以便接收如数据库服务、邮件服务等网络服务。

  • 服务器

服务器则是为其他程序或设备提供功能的计算机或软件。一种专门设计用来处理数据请求并提供服务的计算设备。它具备高速的CPU、大容量的存储空间以及强大的I/O吞吐能力,能够长时间稳定运行。服务器的主要作用是在网络中为客户机(如个人电脑、智能手机等)提供诸如网站访问、文件存储、数据处理等各种计算和应用服务。

  • 网络编程

网络编程 : 指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。

  • 套接字(Socket)

套接字,常称为socket,是计算机网络中用于实现不同主机之间的进程双向通信的端点。在网络编程中,套接字充当了非常重要的角色,它定义了一套标准的API,允许程序员在不同的计算机之间发送和接收数据.是网络编程中实现不同主机间进程通信的一种技术规范和编程接口。

  • 流套字节

使用传输层TCP协议 , 对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。

  • 数据报套接字

使用传输层UDP协议 , 对于数据报来说,可以简单的理解为,传输数据是⼀块⼀块的,发送⼀块数据假如100个字节,必须⼀次发送,接收也必须⼀次接收100个字节,而不能分100次,每次接收1个字节。

  • 原始套字节

原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

  • TCP和UDP的特点

TCP特点:

  1. 有连接 : 连接的双方都需要认同(本质上就是通信双方都保存有通信双方各自的信息)
  2. 可靠传输 : 主要是指发送方放的信息是否被收到 , 发送方能够清楚的感知到.
  3. 面向字节流 : 传输的基本单位是以字节为基本单位
  4. 全双工 : 一个信道,可以双向通信. 只能单向通信就称为’‘半双工’’

UDP的特点:
1.无连接. 2. 不可靠传输. 3.面向字节报 4.全双工.

二.常用API

DatagramSocket
构造方法:
在这里插入图片描述
常用方法:
在这里插入图片描述
DatagramPacket
构造方法:
在这里插入图片描述
基本方法:
在这里插入图片描述

三.基于UDP回显服务器.

客户端代码

package Demo1;

import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class udpEchoClint {
    private DatagramSocket datagramSocket = null;
    private String  serverIP;
    private int serverPort;
    //客户端要给服务器发送请求的前提就是知道服务器的地址
    public udpEchoClint(String serverIP,int serverPort) throws SocketException {
        datagramSocket = new DatagramSocket();
        this.serverIP= serverIP;
        this.serverPort = serverPort;
    }
    public void start() throws IOException {
        System.out.println("客户端启动~~");
        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.print("->");
            if(!scanner.hasNext()){
                break;
            }
            //1.从控制台读取要发送的请求数据.
            String request = scanner.next();
            //2.构造一个请求并发送.
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),
                    request.getBytes().length,
                    InetAddress.getByName(serverIP),
                    serverPort
                    );
            datagramSocket.send(requestPacket);
            //3.读取服务器的响应.
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            datagramSocket.receive(responsePacket);
            //4.把响应显示到控制台上
            String response = new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }
    }
    public static void main(String[] args) throws IOException {
        udpEchoClint clint = new udpEchoClint("127.0.0.1",9090);
        clint.start();
    }
}

服务器代码

package Demo1;

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

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){
            //每次循环就是处理一个请求返回响应的过程
            //1.读取请求并解析
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
                //这个字节数组,保存收到的消息正文(应用层数据包),也就是应用层数据报的载荷部分
            datagramSocket.receive(requestPacket);
                //将消息正文转化为字符串.
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());
            //2.根据请求计算响应(对于回显服务器来说,这一步啥也不用干)
            String response = process(request);
            //3.把响应返回给客户端
            //构造一个响应对象.
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(StandardCharsets.UTF_8),
                    response.getBytes().length,
                    requestPacket.getSocketAddress() //得到一个INetAddress对象吗,里面存储了客户端的IP和端口号.
                    // 会把客户端的源IP和端口号,作为目的IP和目的端口号.

            );
            datagramSocket.send(responsePacket);

            //打印日志:
            System.out.printf("[%s,%d],request: %s, response: %s",
                    responsePacket.getAddress().toString(),
                    responsePacket.getPort(),
                    request,
                    response
            );
        }
    }
    public String process(String request){
        //回显服务器,返回要求.
        return request;
    }
    public static void main(String[] args) throws IOException {
        udpEchoServer server = new udpEchoServer(9090);
        //1024<端口号范围<65535
        server.start();
    }
}

运行结果:
在这里插入图片描述
在这里插入图片描述
具体的执行流程:

  1. 服务器启动===>启动之后,立即进入while循环,执行到receive,进入阻塞,此时客户端还没有发来请求~~
  2. 客户端启动===>启动之后,立即进入while虚幻,执行到hasNext这里~~进入阻塞,此时用户没有在控制台输入任何内容.
  3. 用户在客户端的控制台中输入字符串,按下回车.此时hasNext阻塞解除,next会返回刚才输入的内容.
    基于用户输入的内容,构造出一个DatagramPacket对象,并进行send~~
    send执行完毕之后,继续执行到receive操作,等待服务器返回的响应数据(此时服务器还没有返回响应,这里也会阻塞).
  4. 服务器收到请求之后,就会从receive的阻塞中返回.
    返回之后,就会根据读到的DatagramPacket对象,构造String request,通过process方法构造一个String response
    再根据response构造一个DatagramPacket表示响应对象,再通过send来进行发送给客户端
    执行这个过程中,客户端也始终在阻塞等待!!
  5. 客户端从receive中返回执行,就能够得到服务器返回的相应.并且打印在控制台上.
    于此同时,服务器进入下一次循环,也要进入到第二次的receive阻塞,等待下个请求~~

四.编写一个英译汉的服务器

利用上述写的回显服务器.只需要重写process
代码示例:

package Demo1;

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

public class UdpDictServer extends udpEchoServer{
    HashMap<String,String> hashMap = new HashMap<>();
    public UdpDictServer(int port) throws SocketException {
        super(port);
        hashMap.put("cat","小猫");
        hashMap.put("dog","小狗");
        hashMap.put("pig","小猪");
    }
    @Override
    public String process(String request) {
        return hashMap.getOrDefault(request,"您输入的单词不存在");
    }

    public static void main(String[] args) throws IOException {
        UdpDictServer server = new UdpDictServer(9090);
        server.start();
    }
}

运行结果:
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

虚拟机中安装的CentOS7的桌面右上角没有网络图标解决方案

问题描述 今天在打开CentOS7后&#xff0c;发现右上角的网络图标不见了&#xff0c;然后命令行访问百度也不通。然后上网查了一些解决方法。 原因分析及解决方案&#xff1a; 上网查了许多解决方法&#xff0c;其中一种成功解决了我的问题&#xff1b;我的是配置文件的问题。…

双链向表专题

1.链表的分类 链表的种类非常多组合起来就有 2 2 8种 链表说明&#xff1a; 虽然有这么多的链表的结构&#xff0c;但是我们实际中最常⽤还是两种结构&#xff1a; 单链表 和 双向带头循环链表 1. 无头单向⾮循环链表&#xff1a;结构简单&#xff0c;⼀般不会单独⽤来存数…

在linux系统中启动pycharm

1.找到pycharm的安装路径&#xff0c;一般在下载文件夹中 2.进入pycharm的安装路径&#xff0c;进入bin目录 3.右击&#xff0c;打开终端&#xff0c;输入./pycharm.sh

Linux系统中Nginx的使用

Nginx是一款开源的高性能、高可靠性的Web服务器和反向代理服务器。它在Linux系统中得到了广泛的应用&#xff0c;被用于构建高性能的Web应用和提供反向代理服务。下面将介绍Nginx在Linux系统中的使用以及一些常见的应用案例。 一、Nginx的安装和配置 安装Nginx 在Linux系统中…

2024深圳杯数学建模挑战赛B题:批量工件并行切割下料问题思路代码成品论文分析

更新完整代码和成品完整论文 《2024深圳杯&东三省数学建模思路代码成品论文》↓↓↓ https://www.yuque.com/u42168770/qv6z0d/zx70edxvbv7rheu7?singleDoc# 问题重述 深圳杯数学建模挑战赛2024B题&#xff1a;批量工件并行切割下料问题 板材切割下料是工程机械领域重要…

hyperf 三十一 极简DB组件

一 安装及配置 composer require hyperf/db php bin/hyperf.php vendor:publish hyperf/db 默认配置 config/autoload/db.php 如下&#xff0c;数据库支持多库配置&#xff0c;默认为 default。 配置项类型默认值备注driverstring无数据库引擎 支持 pdo 和 mysqlhoststringl…

python_django中小学家校互动系统vue_flask家校联系

实现了一个完整的家校互动系统&#xff0c;其中主要有作业信息模块、学校管理员模块、学生学籍模块、学生成绩模块、学科模块、系统新闻模块、系统公告模块、校内新闻模块、校内公告模块、用户表模块、token表模块、关于我们模块、收藏表模块、年级模块、家长模块、教师模块、互…

贪心算法练习day.1

理论基础 贪心算法是一种常见的解决优化问题的方法&#xff0c;其基本思想就是在问题的每个决策阶段&#xff0c;都选择当前看起来最优的选择&#xff0c;即贪心地做出局部的最优决策&#xff0c;以此得到全局的最优解&#xff0c;例如在十张面额不同的钞票&#xff0c;让我们…

mysql-connector 交叉编译

1.下载 官网选择对应的系统以及版本&#xff0c;这里我用的是6.1.5https://downloads.mysql.com/archives/c-c/ 2.解压 tar -zxvf mysql-connector-c-6.1.5-src.tar.gz 3.先常规编译&#xff08;因为交叉编译的过程中&#xff0c;会用到生成的二进制文件&#xff09; cd m…

PCB元器件的符号和封装

打开立创商店&#xff1a; PCB是用来链接器件和让电路小型化的 符号&#xff1a; 封装&#xff1a; 封装是在PCB板上呈现的方式 紫色&#xff1a;不需要上绿由 红色: 焊盘 黄色: 丝印层 也就是白色的这个 焊盘 焊盘是为了让接触点增大&#xff0c;更好的焊接元件 焊盘…

ardupilot开发 --- 机载(边缘)计算机-VISP高阶 篇

让我再看你一眼从南到北 0. 基础1. 视觉伺服1.1 视觉伺服基础1.1.1 基本理论1.1.2 代码解析(tutorial-ibvs-4pts.cpp)&#xff1a; 1.2 基于图像处理的视觉伺服 0. 基础 基础知识点请参考基础篇。 1. 视觉伺服 参考&#xff1a;Visual servoing 1.1 视觉伺服基础 参考1&am…

达芬奇调色:色彩理论入门

写在前面 整理一些达芬奇调色的笔记博文内容涉及&#xff1a; 一级调色是什么&#xff0c;以及 调色素材格式 log&#xff0c;raw&#xff0c;rec709 简单认知理解不足小伙伴帮忙指正 不必太纠结于当下&#xff0c;也不必太忧虑未来&#xff0c;当你经历过一些事情的时候&#…

全网最全搭建Electron项目的各种方式及错误解决

一、官方文档手动搭建 文档地址&#xff1a;快速入门 | Electron&#xff0c;按照文档步骤操作即可&#xff0c;项目只包含了Electron依赖&#xff0c;仅仅只是一个hello world展示。 二、github上拉取官网的electron-quick-start项目 electron-quick-start跟方式一创建的一…

MySQL数据库运维:运行监控及解决sql执行死锁问题

前言 在现代数据密集型应用程序的开发和部署中&#xff0c;MySQL数据库的运维是至关重要的环节之一。一个良好设计和维护的MySQL数据库系统可以确保数据的准确性、可靠性和高效的访问&#xff0c;从而支持业务的顺利运行。然而&#xff0c;随着业务规模的增长和复杂性增加&…

Spring 5源码学习

文章目录 一. 访问[spring官网], 找到Spring Framework&#xff0c;点击红色标记github仓库&#xff0c;下载对应的分支代码&#xff0c;本人下载5.1.x二. 安装gradle三. 调整spring-framework配置四. 开始编译五.导入idea 一. 访问[spring官网], 找到Spring Framework&#xf…

使用Python和wxPython下载视频封面

介绍&#xff1a; 在在线视频内容的世界中&#xff0c;是领先的平台。拥有数十亿的视频&#xff0c;拥有引人注目的封面图像非常重要&#xff0c;以吸引观众。在本博客文章中&#xff0c;我们将探讨如何使用Python和wxPython模块下载视频封面。我们将提供两个代码示例&#xff…

图像数据做并行规约时,如何确定共享内存和网格的大小

做并行规约时&#xff0c;如何确定共享内存和网格的大小 1、为什么要确定共享内存和网格大小2、共享内存大小定义3、网格大小 注&#xff1a;1、这里记录使用笔记&#xff0c;不对cuda的名词做解释&#xff0c;没有详细数学原理和代码。 2、环境&#xff1a;cuda8.0&#xff0c…

密码学 | Random Oracle 随机预言机

​ &#x1f951;原文&#xff1a;究竟什么才是随机预言机呢&#xff1f; - 玄星的回答 &#x1f951;答主指出&#xff1a; 英文维基明明对 随机预言机 给出了两个完全不同的理解&#xff0c;但这两个理解之间的连接词却是 “Stated differently”&#xff0c;即 “换句话说…

STM32通过ESP8266(MQTT)连接新版ONENET(2024/4/23)(保姆级教程)附运行结果

⏩ 大家好哇&#xff01;我是小光&#xff0c;想要成为系统架构师的嵌入式爱好者。 ⏩在各种嵌入式系统中我们经常会使用上位机去做显示&#xff0c;本文对STM32通过ESP8266连接最新版的ONENET做一个详细教程。 ⏩感谢你的阅读&#xff0c;不对的地方欢迎指正。 STM32通过ESP82…

【图说】VMware Ubuntu22.04 详细安装教程

前言 无论是从事 Linux 开发工作&#xff0c;还是希望电脑运行双系统&#xff0c;VMware 虚拟机都是我们日常工作不可或缺的工具。本章将会重点介绍 VMware 安装流程&#xff0c;以及在 VMware 上如何运行、使用 Ubuntu22.04 系统。 一、VMware 下载安装 1.1 VMware 官网下载…