【网络编程】网络编程概念 | TCP和UDP的区别 | UDP数据报套接字编程 | Socket

文章目录

  • 网络编程
        • 一、什么是网络编程
          • 1.TCP和UDP的区别
        • 二、UDP数据报套接字编程
          • DatagramSocket
          • DatagramPacket
          • 回显服务器(echo server)

网络编程

一、什么是网络编程
  • 通过网络,让两个主机之间能够进行通信。基于通信来完成一定的功能。

​ 进行网络编程的时候,需要操作系统提供一组API,通过这些API来完成。这些API可以认为的应用层和传输层之间交互的路径。这些API称为Socket API。通过一套Socket API 可以完成不同主机、不同系统之间的网络通信。

​ 传输层提供的网络协议主要有两个:TCP、UDP。这两个协议的特性差异很大,会导致使用这两种协议进行网络编程,会存在一定的差别。系统就分别提供了两套API。

1.TCP和UDP的区别

1.TCP是有连接的,UDP是无连接的。

​ 连接是抽象的概念:此处的连接本质上,就是建立连接的双方,各自保存对方的信息。两台计算机建立连接,就是双方彼此保存了对方的关键信息。TCP要想通信,就需要先建立连接(保存对方信息)。存完之后才能通信。

如果A想和B建立连接,但是B拒绝了,通信就无法完成。

​ UDP想要通信,自己不会去保存对方信息。直接发送数据,不需要征求对方同意。(程序员调用UDP的Socket API会传东对方信息)

2.TCP是可靠传输的,UDP是不可靠传输的。

​ 在网络上进行通信,A给B发送消息。并不能保证100%送达。所以这里可靠传输的概念是:A给B发消息。A可以感知到,消息有没有到达B。就可以在发送失败时,采取一定的措施(尝试重传等)。但同时可靠传输的代价就是机制更复杂以及降低传输效率。

​ TCP就内置了可靠传输机制。

3.TCP是面向字节流的,UDP是面向数据报的。

​ TCP也是和文件操作一样,以字节为单位来进行传输。UDP则是按照数据报为单位进行传输。 UDP数据报有严格的格式。

网络通信数据的基本单位:1.数据报(Datagram)2.数据包(Packet)3.数据帧(Frame)4.数据段(Segment)

4.TCP和UDP都是全双工的。

一个信道,允许双向通信,就是全双工。一个信道,只能单向通信,就是半双工。

在代码中使用一个Socket对象,就可以发送数据也能接受数据。

二、UDP数据报套接字编程

​ Socket是操作系统中的概念,本质上是一种特殊的文件。就相当于把“网卡”这个设备抽象成了文件。后续往Socket文件中写数据,就相当于通过网卡发送数据。从Socket文件中读数据,就相当于通过网卡接收数据。把网络通信和文件操作进行统一。

DatagramSocket

在Java中,使用DatagramSocket这个类来表示系统内部的Socket文件。

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

    public UdpEchoServer(int port) throws SocketException {//指定一个端口号
        socket = new DatagramSocket(port);//创建的socket对象绑定这个指定的端口。
    }

在这里插入图片描述

1.这里的send发送 和receive接收方法,传进的参数类型都是DatagramPacket数据报。

2.receive方法中,参数同样是一个“输出型参数”。

DatagramPacket
  • DatagramPacket这个类,表示一个UDP数据报。

    构造方法:

    1.只指定字节数组缓冲区

            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            //用来承载从网卡中读到的数据。收到数据的时候需要搞一个内存空间来保存这个数据
            //DatagramPacket内部不能自行分配内存空间,需要程序员手动创建空间,交给DatagramPacket处理
            socket.receive(requestPacket);

2.指定字节数组缓冲区,同时制定一个InetAdress对象(包含了IP和端口号)

            DatagramPacket responsePacket = new DatagramPacket(
                    response.getBytes(), //指定的数据
                    response.getBytes().length, //数据的长度
                    requestPacket.getSocketAddress());//发送来的地址就是要发送的地址。

    public synchronized SocketAddress getSocketAddress() {
        return new InetSocketAddress(getAddress(), getPort());
    }

3.指定字节数组缓冲区,指定IP + 端口号。

    	 DatagramPacket requestPacket = new DatagramPacket( 
                request.getBytes(), request.getBytes().length,
                InetAddress.getByName(serverIp), serverPort);

​ UDP是面向数据报的,每次进行传输,都要以UDP数据报为基本单位。在DatagramSocket的方法中,接收和发送传入的参数就是DatagramPacket数据报类型。

回显服务器(echo server)
  • 写一个简单的客户端、服务器通信程序。单纯调用Socket API。从控制台上输入一个请求发送给服务器,服务器收到字符串后,原封不动返回给客户端并显示出来。

​ 服务器和客户端都需要创建Socket对象。但是 服务器的socket一般要显示的指定一个端口号。而客户端的socket一般不能显示指定。(不显示指定,系统会自动分配一个随机的端口)

​ 服务器上有哪些程序,都使用哪些端口,都是程序员可控的。写代码时就可以指定空闲的端口,给当前的服务器使用。相比之下,客户端不可控。交给系统分配一个空闲的端口给客户端。所以服务器需要手动指定端口。客户端要交个系统来分配一个空闲端口。

UdpEchoServer

1.读取请求并解析

2.根据请求计算响应(一个服务器最核心的步骤)

3.把响应写回客户端

4.打印一个日志,把这次数据交互的详情打印出来

public class UdpEchoServer {
    //1.先出创建DatagramSocket对象 :后续操作网卡的基础
    private DatagramSocket socket = null;

    public UdpEchoServer(int port) throws SocketException {//指定一个端口号
        socket = new DatagramSocket(port);//创建的socket对象绑定这个指定的端口。
    }

    /**
     * 通过这个方法启动服务器
     */
    public void start() throws IOException {
        System.out.println("服务器启动!");
        //在服务器程序中,经常出现while true的代码
        while (true) {
            //1.读取请求并解析
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            //用来承载从网卡中读到的数据。收到数据的时候需要搞一个内存空间来保存这个数据
            //DatagramPacket内部不能自行分配内存空间,需要程序员手动创建空间,交给DatagramPacket处理
            socket.receive(requestPacket);
            //读取数据,并填充进DatagramPacket,如果没有接收到数据报,receive方法会阻塞等待
            //此时是以二进制的形式存到DatagramPacket中,需要把二进制转换成字符串
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            //获取到字符数组,取[0,getLength]区间内的字节,构造成String. getLength不是4096,是实际的收到的数据长度

            //2.根据请求计算响应(一个服务器最核心的步骤)
            //由于此处是回显服务器,请求是啥样,响应就是啥样。
            String response = process(request);
            //3.把响应写回客户端
            //创建一个响应对象,DatagramPacket,往对象里构造刚才的数据,再通过send进行返回。
            DatagramPacket responsePacket = new DatagramPacket(
                    response.getBytes(), //指定的数据
                    response.getBytes().length, //数据的长度
                    requestPacket.getSocketAddress());//发送来的地址就是要发送的地址。
            //需要指定数据的内容,也要指定数据报要发给谁。
            socket.send(responsePacket);

            //4.打印一个日志,把这次数据交互的详情打印出来
            System.out.printf("[%s:%d] req=%s, resp=%s\n",requestPacket.getAddress().toString(),
                    requestPacket.getPort(),request,response);
        }
    }

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

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
  • 需注意的是,这里并没有写close.因为socket是文件描述符表的一个表项,文件描述符表在PCB上(跟随进程)。
  • socket在整个程序运行的过程中都需要使用,不能提前关闭。当不在再需要时,意味着程序就要结束了,进程结束,文件描述符表就会销毁。随着销毁,被系统自动回收
public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIp = "";
    private int serverPort = 0;

    public UdpEchoClient(String ip, int port) throws SocketException {
        //客户端的socket对象的端口,由系统自动分配
        socket = new DatagramSocket();
        //由于UDP不会持有对端的信息,需要在应用程序里,把对端的情况记录下来。
        serverIp = ip;
        serverPort = port;
    }

    public void start() throws IOException {
        System.out.println("客户端启动!");
        Scanner scanner = new Scanner(System.in);
        while (true) {
            //1.从控制台读取数据,作为请求
            System.out.print("->");
            String request = scanner.next();
            //2.把请求内容构造成DatagramPacket对象,再发给服务器
            DatagramPacket requestPacket = new DatagramPacket(
                    request.getBytes(), request.getBytes().length,
                    InetAddress.getByName(serverIp), serverPort);//把转换字符串ip
            socket.send(requestPacket);
            //3.尝试读取服务器返回的响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);
            //4.把响应,转换成字符串,并显示出来
            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",9090);
        client.start();
    }

1.服务器先启动,服务器启动之后,就会进入循环,执行到receive这里并进行阻塞

2.客户端开始启动,也会先进入while循环,执行到scanner.next,进行阻塞。当用户输入完成后,next就会返回,从而构造请求数据并进行发送给服务器。

3.服务器从receive中返回,进一步执行解析请求为字符串,执行process操作,执行send操作。

与此同时,客户端继续往下执行,执行到receive等待服务器的响应,进行阻塞。

4.客户端收到从服务器返回的数据后,就会从receive中返回,执行打印

5.服务器完成一次循环后,有执行到receive进行阻塞。客户端完成一次循环后,又执行到scanner.next进入阻塞,直到用户进行输入。

点击移步博客主页,欢迎光临~

偷cyk的图

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

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

相关文章

MacOS 下gif 文件的几种压缩方法

categories: Tips tags: Tips GIF 写在前面 最近想转换几个 tg 的 tgs 文件到 gif, 然后上传到微信, 所以又涉及到了 gif 的操作了. 工具介绍 安装 brew install imagemagick gifsicleimagemagick 是专业的图像处理工具, gifsicle 是专门处理 gif 的小工具 ,都是开源的. …

C++之AVL树的使用以及原理详解

1.AVL树 1.1AVL树的概念 1.2AVL树的定义 1.3AVL树的插入 1.4AVL树的旋转 1. 右单旋 2. 左单旋 3. 左右双旋 4. 右左双旋 1.5AVL树的验证 1.6AVL的实现 在之前对map/multimap/set/multiset进行了简单的介绍(C之map_set的使用-CSDN博客),…

说说2024年暑期三下乡社会实践工作新闻投稿经验

作为一名在校大学生,我有幸自去年起参与学院组织的暑期大学生三下乡社会实践团活动。这项活动不仅是我们深入基层、服务社会的重要平台,也是展现当代大学生风采、传递青春正能量的有效途径。然而,如何将这些生动鲜活的实践故事、感人至深的瞬间传播出去,让更多人了解并受到启发…

火绒安全的应用介绍

火绒安全软件是一款集成了杀毒、防御和管控功能的安全软件,旨在为用户提供全面的计算机安全保障。以下是火绒安全软件的一些详细介绍: 系统兼容性强:该软件支持多种操作系统,包括Windows 11、Windows 10、Windows 8、Windows 7、…

xgp加速器免费 微软商店xgp用什么加速器

2001年11月14日深夜,比尔盖茨亲自来到时代广场,在午夜时分将第一台Xbox交给了来自新泽西的20岁年轻人爱德华格拉克曼,后者在回忆中说:“比尔盖茨就是上帝。”性能超越顶级PC的Xbox让他们趋之若鹜。2000年3月10日,微软宣…

25-代码随想录第454题.四数相加II

25-代码随想录第454题.四数相加II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] B[j] C[k] D[l] 0。 为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范…

python 笔记ast.literal_eval

1 介绍 ast.literal_eval 是 Python 标准库 ast 模块中的一个函数,用于安全地评估表示 Python 字面量或容器(如列表、字典、元组、集合)的字符串 import ast # 解析并执行一个数字表达式 num ast.literal_eval("3.14") prin…

OpenFeign微服务调用组件!!!

1.Feign是什么 GitHub - OpenFeign/feign: Feign makes writing java http clients easierFeign makes writing java http clients easier. Contribute to OpenFeign/feign development by creating an account on GitHub.https://github.com/OpenFeign/feignFeign是Netflix开…

项目十一:爬取热搜榜(小白实战级)

首先,恭喜各位也恭喜自已学习爬虫基础到达圆满级,今后的自已python爬虫之旅会随着网络发展而不断进步。回想起来,我学过请求库requests模块、解析库re模块、lmxl模块到数据保存的基本应用方法,这一次的学习python爬虫之旅收获很多…

Vu3+QuaggaJs实现web页面识别条形码

一、什么是QuaggaJs QuaggaJS是一个基于JavaScript的开源图像识别库,可用于识别条形码。 QuaggaJs的作用主要体现在以下几个方面: 实时图像处理与识别:QuaggaJs是一款基于JavaScript的开源库,它允许在Web浏览器中实现实时的图像…

ASP.NET Core 3 高级编程(第8版) 学习笔记 03

本篇介绍原书的第 18 章,为 19 章 Restful Service 编写基础代码。本章实现了如下内容: 1)使用 Entity Framework Core 操作 Sql Server 数据库 2)Entity Framework Core 数据库迁移和使用种子数据的方法 3)使用中间件…

Qt Quick centerIn和fill 的用法

1)Qt Quick centerIn和fill 的用法: import QtQuick 2.5 Rectangle { width:300; height:200; Rectangle { color: "blue"; anchors.fill: parent; border.width: 6; border.co…

详解工业网关在线探测功能及用途

工业网关专为工业物联网应用设计,可实现包括不同通讯协议之间的兼容和转换,提供软硬件加密保障工业数据安全传输,发挥强大算力实现数据边缘预处理,联动联调工业网络设备实现高效协同等。在线探测功能是佰马工业网关的一项重要功能…

unity学习(89)——unity塞满c盘!--删除editor下的log文件

卸了一个视频后强制续命打开详细信息: 这个再往下找也是没用的! 显示隐藏文件夹后!执行如下操作! 30个g! 其中unity占23g editer占了21g 删除C:\Users\王栋林\AppData\Local\Unity\Editor下的log文件 恢复到之前的水…

使用 Flask 和 WTForms 构建一个用户注册表单

在这篇技术博客中,我们将使用 Flask 和 WTForms 库来构建一个用户注册表单。我们将创建一个简单的 Flask 应用,并使用 WTForms 定义一个注册表单,包括用户名、密码、确认密码、邮箱、性别、城市和爱好等字段。我们还将为表单添加验证规则&…

【C 数据结构】图

文章目录 【 1. 基本原理 】1.1 无向图1.2 有向图1.3 基本知识 【 2. 图的存储结构 】2.1 完全图2.2 稀疏图和稠密图2.3 连通图2.3.1 (普通)连通图连通图 - 无向图非连通图 的 连通分量 2.3.2 强连通图强连通图 - 有向图非强连通有向图 的 强连通分量 2.3.3 生成树 - 连通图2.3…

美区视频带货“一哥”,一周销量狂干三十万美金!

“超店有数显示,Tybuggy上周带货狂揽34.3万美金,超出第二名近30倍。” TikTok风波再起,4月17日,美众议院推出援乌援以军事议案,值得注意的是,TikTok剥离法案被“打包”夹带其中,以此加大再参议…

LLM应用实战:当KBQA集成LLM(二)

1. 背景 又两周过去了,本qiang~依然奋斗在上周提到的项目KBQA集成LLM,感兴趣的可通过传送门查阅先前的文章《LLM应用实战:当KBQA集成LLM》。 本次又有什么更新呢?主要是针对上次提到的缺点进行优化改进。主要包含如下方面&#…

【Linux笔记】基本指令(一)

一道残阳铺水中 半江瑟瑟半江红 目录 Linux基本指令 罗列目录内容:ls 指令 显示当前目录位置信息:pwd 指令 切换工作目录:cd 指令 创建文件修改时间戳:touch指令 创建空目录:mkdir指令 删除空目录:rmdir指…

1.3K Star我上位机项目中用了这个开源项目

软件介绍 ClientServerProject的软件是一款基于C-S(客户端-服务器)架构的通用开发框架,为中小型系统的快速开发提供强大的支持。该框架由服务端、客户端以及公共组件三部分组成,不仅提供了基础的账户管理、版本控制、软件升级、公…
最新文章