网络编程概念详解模拟回显客户端服务器
目录
1.网络中重要的概念
1)IP地址:
2)端口号:
3)协议
协议分层
OSI七层模型(教科书)
TCP/IP五层模型
封装和分用
网络套接字
面试题:TCP/UDP的区别?
UDP数据报套接字编程
模拟一个回显客户端-服务器
1.网络中重要的概念
在网络通信中,如何区别是从哪台主机将数据传输到哪台主机上呢?这就需要IP地址来标识。
1)IP地址:
IP地址描述了一台主机在互联网上的位置,IP地址是使用一个32位的二进制数表示的,通常被分为4个“8位二进制数”也就是4个字节。
使用“点分十进制”这样的方式来表示“IP地址”。这样的方式更有利于人们的阅读。
2)端口号:
标识主机中发送数据,接收数据的进程,定位主机上的指定位置应用程序(进程)
一个主机上使用网络有的很多个程序,通过端口号区分,当前主机收到的数据是要交给哪些程序来使用。端口号同样也是一个整数,一个2个字节的整数。
虽然端口号是0->65535范围,但是0->1023这些端口都是有特定含义的,我们一般使用这个范围之外的。
问题:有了IP地址和端口号就可以定位网络中的唯一进程,但是网络通信是基于二进制0/1数据来传输的,如何告诉对方发送的数据是什么样呢?因为数据的形式多种多样,有文字有图片等等
3)协议
网络协议简称协议,所有网络数据传输经过所有的网络设备都必须遵守的规则,比如怎么样建立链接,怎么样相互识别。遵守统一的规则计算机才能相互通信交流。
协议最终体现为网络传输数据包的格式。
为什么需要协议?
计算机传播的媒介是光信号和电信号,通过"频率","强弱"来表示0/1,相传数不同的信息就需要约定好双方的数据格式
- 计算机的生厂商很多
- 计算机操作系统很多
- 计算机网络硬件设备也很多
如果让这些厂商生产的计算机顺利通信,就必须要有一个共同的标准来遵守
协议分层
了解协议之后,如何进行网络通信的问题就转化为如何设计网络通信协议
网络传输数据依靠光信号,电信号,电磁波,本质上是传输010101这样的一串二进制,通信时就需要约定好这串数字是什么意思..
由于网络通信十分复杂,仅仅一个协议约定网络通信中所有细节是不可能的.所以就会把一个大协议拆分许多小的协议,去解决某一类问题,再让这些小协议相互配合------协议分层
约定好,协议之间不能i相互调用,只能上层调用下层协议; 图中的最后就叫做 协议栈/协议族
协议分层的好处?
- 降低使用的成本,使用某个协议的时候不需要关注其他协议的实现细节.
- 降低整个协议的耦合性,灵活的变更某个层次的协议
OSI七层模型(教科书)
七层模型过于复杂不实用,所以只存在与教科书上,没有被应用.
TCP/IP五层模型
物理层考虑的较少,所以有时候就是四层模型
- 应用层负责程序之间的沟通,程序具体要做什么事情.程序员网络编程主要负责这一层的处理
- 传输层只关心网络通信中的起点和终点,不关心通信的中间细节
- 网络层进行网络通信的中间路径规划,还需要负责地址的管理
- 数据链路层针对上述规划的路径进行具体的实施
- 物理层描述的是硬件设备需要描述的物理设备需要什么条件
设备驱动程序是操作系统和硬件通信,管理硬件使用的程序,驱动程序是厂商配套使用的.
主机实现了从传输层到物理层,也就是下四层模型
路由器实现了网络层到物理层下三层结构
交换机实现数据链路层到物理层的下两层结构
集线器只实现了物理层
这里说的交换机与路由器都是传统意义上的机器,现在随着技术发展已经可以实现3/4层的交换机,4层路由器.
所以真实情况下,交换机可能工作在网络层 甚至传输层,路由器也可能工作在数据链路层和网络层,甚至应用层.
封装和分用
封装就类似于字符串的拼接
在使用通信工具的时候,在输入框内一个内容发送; 这个内容就被读取构造成一个"应用层数据包"
应用层网络协议就描述了数据包的构造. 一般应用层的协议是程序员自己定义的.
例举一个定义应用层数据包的案例.
1.将内容打包成应用层数据包
数据包的格式: 发送者的账号_接受者的账号_发送时间_消息正文\n
数据包的样例: 1234567890_20520863360_2024-08-8-12:00:00_hellow\n;
进行网络传输数据 通常需要把一个结构化的数据转化成一个字符串;
把结构化的数据转化成二进制字符串 这个过程为序列化;
把二进制字符串转化为一个结构化的数据 这个过程为反序列化
2.通信应用程序会调用操作系统提供的API (传输层给应用层提供的API)
操作系统会提供一个类似"发送数据"这样的API,然后应用程序就会把上述组织好的应用层数据包作为参数传进来,于是应用层数据包就到了系统内核里面,就进入到传输层的代码部分中去.
此时.传输层就会把上述应用层数据包封装成一个传输层数据包. 传输层有多种协议其中最主要的是TCP和UDP,假设此处使用的是UDP.看你代码中具体是哪种API就调用哪个协议.
计算机的封装就类似于字符串的拼接,
3.传输层构造好数据之后,就会继续调用网络层给传输层提供的API,把数据进一步交给网络层.
网络层里也有很多协议,最主要的是IPv4协议(简称`IP协议). 当然还有IPv6,但是当前仍是IPv4占主导地位,所以这里默认是IPv4.
IP协议就会把上述的 传输层数据包构造成 网络层数据包
4.网络层继续调用API,把数据交给数据链路层处理
数据链路层常见的协议是以太网(平时插网线,进行上网的这种方式)
5.上述的数据进一步交给物理层(硬件设备)
网卡就会针对上述的二进制数据,进行真正的传输操作.就需要把数据0101这样的序列,转化为光信号/电信号/电磁波.
接收方视角,此处做的工作就是发送方的逆向工作,发送方的封装认为是快打包,接受就是快递拆解。
1.接收光电信号,把这样的信号还原成101001这样的二进制字符串
2.物理层转换回来的数据交给数据链路层,以太网拿到这个数据包,就会对其进行解析.
拿出这里的报头与载荷,根据报头中的一些信息,做出一些处理. 根据报头信息决定是丢弃还是转发,还是保留(向上解析)
3.网络层拿到上述解析好的数据,也要对其进一步解析,取出IP报头和荷载。
拿出报头数据后也要进行解析,取出IP报头 与 载荷,决定是丢弃转发 或者是保留
4.传输层这边UDP协议,取出UDP报头 和 载荷
此处需要把载荷里的内容交给应用层协议,依赖UDP报头中的“端口号” ,端口号就是来区分不同的进程的。
5.数据就到了通信应用这样的程序里了
通信程序就要针对数据进行“反序列化”,针对这里的数据进行进一步的逻辑。
- 需要把收到的消息显示到界面上
- 播放消息铃声,提醒收到消息
- 显示弹窗
- 更新未读的消息列表
总结:什么是封装 与 分用
封装:就是将数据从一个层级 包装 到另一个层级的过程。在网络传输中 数据从应用层到物理层会经历的多层包装。以上发送信息的举例就是封装。
分用:就是 封装的反过程,即从物理层到应用层 逐步剥离各个层级的包装。在接收端,数据最终被还原为原始的应用数据。
在封装与分用的过程中可能存在很多交换机 路由器完成数据转发的过程。
中间过程的交换机 路由器也会涉及到 封装与分用。
交换机封装到 数据链路层决定数据是丢弃还是继续转发,不再继续分用(教科书上的交换机)
路由器封装分用到网络层,可以决定是数据继续转发 还是丢弃。
网络套接字
Socket套接字
是由系统提供的用于网络通信技术,基于TCP/UDP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。
本身为插槽的意思,是操作系统给应用程序传输层给应用层)提供的API。
这个API有两种,一种是TCP,一种是UDP
面试题:TCP/UDP的区别?
TCP有连接,可靠传输,面向字节流,全双工
UDP无连接,不可靠传输,面向数据报,全双工
解释:
有无连接:就是通信双方是否保留了通信对端的信息,保留就相当于是“有连接”,不保留就是“无连接”。
可靠不可靠传输:就是能不能将数据传输到对端,这里的可靠也不是%100,而是大概率。
TCP内置了一些机制能够保证可靠传输:
1.感知到对方是不是收到了
2.重传机制,在对方没有收到的时候进行重试。
UDP没有重传机制,也不管数据有没有顺利达到对端。
面向字节流:TCP传输的过程就和文件流/水流一样特点。
面向数据报:传输数据的基本单位不是字节而是 ”UDP数据报“,一次发送或者接受的就是一个 UDP数据报。
全双工:一个通信链路,可以发送数据,也可以接收数据(双向通信)
半双工:一个通信链路,只能发送/只能接收(单向通信)
UDP数据报套接字编程
DatagramSocket:代表一个Socket对象,通过代码直接操作网卡,不好操作,通过操作系统把网卡封装成Socket,应用程序不关心硬件差异 统一操作Socket对象,就能间接操作网卡。
DatagramSocket 是UDP Socket,⽤于发送和接收UDP数据报。
DatagramSocket 构造⽅法:
⽅法签名 | ⽅法说明 |
DatagramSocket() | 创建一个UDP数据报嵌套字的Socket,绑定到本机任意一个随机端口(一般用于客户端) |
DatagramSocket(int port) | 创建一个UDP数据报嵌套字Socket,绑定到本机指定端口(一般用于服务器) |
DatagramSocket ⽅法:
⽅法签名 | ⽅法说明 |
void receive(DatagramPacket p) | 从此套接字接收数据报(如果没有接收到数据报,该⽅法会阻塞等待) |
void send(DatagramPacket p) | 从此套接字发送数据报包(不会阻塞等待,直接发送) |
void close() | 关闭此数据报套接字 |
模拟一个回显客户端-服务器
服务器代码:
package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}// 通过 start 启动服务器的核心流程public void start() throws IOException {System.out.println("服务器启动!");while (true) {// 此处通过 "死循环" 不停的处理客户端的请求.// 1. 读取客户端的请求并解析DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(requestPacket);// 上述收到的数据, 是二进制 byte[] 的形式体现的. 后续代码如果要进行打印之类的处理操作// 需要转成字符串才好处理.String request = new String(requestPacket.getData(), 0, requestPacket.getLength());// 2. 根据请求计算响应, 由于此处是回显服务器. 响应就是请求.String response = process(request);// 3. 把响应写回到客户端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(), 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();}
}
客户端代码:
package network;import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIP;private int serverPort;public UdpEchoClient(String serverIP, int serverPort) throws SocketException {socket = new DatagramSocket();this.serverIP = serverIP;this.serverPort = serverPort;}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. 构造出一个 UDP 请求, 发送给服务器.DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,InetAddress.getByName(this.serverIP), this.serverPort);socket.send(requestPacket);// 3. 从服务器读取到响应DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);socket.receive(responsePacket);String response = new String(responsePacket.getData(), 0, responsePacket.getLength());// 4. 把响应打印到控制台上.System.out.println(response);}}public static void main(String[] args) throws IOException {// UdpEchoClient client = new UdpEchoClient("47.108.28.88", 9090);UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);client.start();}
}
相关文章:

网络编程概念详解模拟回显客户端服务器
目录 1.网络中重要的概念 1)IP地址: 2)端口号: 3)协议 协议分层 OSI七层模型(教科书) TCP/IP五层模型 封装和分用 网络套接字 面试题:TCP/UDP的区别? UDP数据报套接字编程 模拟一个回…...
代码随想录第二十四天|动态规划(8)
目录 LeetCode 300. 最长递增子序列 LeetCode 674. 最长连续递增序列 LeetCode 718. 最长重复子数组 LeetCode 1143. 最长公共子序列 LeetCode 1035. 不相交的钱 LeetCode 53. 最大子序和 LeetCode 392. 判断子序列 总结 LeetCode 300. 最长递增子序列 题目链接&#…...
编程-设计模式 3:单例模式
设计模式 3:单例模式 定义与目的 定义:单例模式确保一个类只有一个实例,并提供一个全局访问点来访问该实例。目的:这种模式通常用于那些需要频繁访问且只需一个实例的对象,例如配置管理器、日志记录器等。 实现示例…...
Kaniko 构建 Docker 镜像
Kaniko 主要用于构建 Docker 镜像,而不是运行程序。它的主要用途是从 Dockerfile 构建容器镜像,但它并不负责运行容器或程序。以下是 Kaniko 的主要功能和局限性: 主要功能 构建镜像:Kaniko 从 Dockerfile 构建容器镜像。它通过…...

Javascript常见算法(每日两个)
合并两个有序链表 在JavaScript中,合并两个有序链表通常指的是将两个已经按照某种顺序(如升序或降序)排列的链表合并成一个新的有序链表。由于JavaScript本身不直接支持链表数据结构,我们通常会用对象或数组来模拟链表的行为。但…...

Spring -- 事务
Spring中事务的操作分为两类:(1)编程式事务 – 手动写代码操作事务(2)声明式事务 – 利用注解开启事务和提交事务 1. 编程式事务 准备Controller RestController RequestMapping("/user") public class UserInfoController {Autowiredprivate UserInfoService use…...

生命密码的破译者:AI如何学会读懂DNA语言?
引言 如果能像解读一本神秘的书籍那样,理解DNA的“语言”,将是多么令人兴奋的科学突破!如今,这正在逐步变为现实。科学家们训练出的AI模型GROVER正如一个勤奋的学生,学习着DNA的每一个“单词”和“语法”,…...

大数据信用报告查询哪家平台的比较好?
相信在搜索大数据信用的你,已经因为大数据信用不好受到了挫折,想详细了解一下自己的大数据信用,但是找遍了网络上的平台之后才发现,很多平台都只提供查询服务,想要找一个专业的平台查询和讲解很困难。下面本文就为大家…...
Java高级Day24-集合最后补充
75.HashTable 基本介绍: 存放元素的健值对 即K-V hashtable的键和值都不能为null,否则会抛出NullPointerException hashtable使用方法基本上和HashMap一样 hashtable是线程安全的,hashmap是线程不安全 扩容机制: 底层有数组…...

C++入门:C语言到C++的过渡
前言:C——为弥补C缺陷而生的语言 C起源于 1979 年,当时 Bjarne Stroustrup 在贝尔实验室工作,面对复杂软件开发任务,他感到 C 语言在表达能力、可维护性和可扩展性方面存在不足。 1983 年,Bjarne Stroustrup 在 C 语言…...

了解MVCC
概念 MVCC,全称Multi-Version Concurrency Control,即多版本并发控制,是一种并发控制的方法,维护一个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现…...

WPF自定义控件的应用(DynamicResource的使用方法)
1 DynamicResource的使用方法 可以在字典文件 的抬头区写入数: <SolidColorBrush x:Key"PrimaryBackgroundColor" Color"#FFABAdB3"/><SolidColorBrush x:Key"TextBox.MouseOver.Border" Color"#FF7EB4EA"/>&l…...
Postgresql数据库密码忘记的解决
当您忘记PostgreSQL数据库的密码时,可以通过以下步骤来重置密码。这些步骤在Windows和Linux操作系统上大体相同,但具体操作路径和命令可能有所不同。 步骤一:找到并修改pg_hba.conf文件 定位安装目录: Windows:通常在PostgreSQL的安装目录下的data文件夹中。Linux:位置可…...
Flink SQL 基础操作
Flink SQL是建立在Apache Flink之上的SQL处理引擎,它允许用户以SQL的方式处理流数据和批数据。以下是一些Flink SQL的基础操作: 一、环境准备 1.启动flink集群 ./start-cluster.sh启动sql-client ./sql-client.sh二、数据源定义 创建表(…...

海思AE模块Lines_per_500ms参数的意义
基础知识 1秒(S)1000毫秒(ms)1000_000微妙(s)1000_000_000纳秒(ns) 1GHz1000Mhz1000_000KHz1000_000_000Hz 1Hz1/s 抗频闪原理 海思AE模块参数中有一个LinesPer500ms的参数,意思为500ms对应的曝光行数。此个参数和抗频闪有关。 我们知道: 50HZ…...

【代码随想录】区间和——前缀和方法
本博文为《代码随想录》学习笔记,原文链接:代码随想录 题目 原题链接:58. 区间和(第九期模拟笔试) 题目描述 给定一个整数数组 Array,请计算该数组在每个指定区间内元素的总和。 输入描述 第一行输入为…...
Bug 解决 | 前端项目无法正确安装依赖?
目录 1、网络问题 2、权限问题 3、版本冲突 4、缓存问题 5、依赖配置错误 6、系统环境问题 前端项目和后端项目一样,都需要用到很多第三方的类库依赖。目前基本上我们主流的前端项目都使用 Npm、Yarn 等包管理工具来管理项目依赖,正常情况下通过执…...

【mysql 第四篇章】bin log 的作用是啥呢?
一、redo Log 介绍 redo log 是一种偏向物理性质的重做日志,因为他里面记录类似的这样的东西,“对那个数据也中的什么记录,做了个什么修改”。它是 InnoDB 存储引擎特有的东西。 二、bin Log 日志 bin log 叫做归档日志,它里面…...

Linux 操作系统:基于环形队列的生产者消费者模型
Linux 操作系统:基于环形队列的生产者消费者模型 一、前言二、大致框架二、P操作、V操作三、生产者生产数据四、生产者获取数据五、代码测试六、所有代码 一、前言 环形队列采用数组模拟,用模运算来模拟环状特性。和基于阻塞队列的生产者消费者模型不同的…...
python求解二次方程
为了找到x和y之间的关系,并假设这种关系是一个二次函数,我们可以使用numpy的polyfit函数来拟合一个二次方程(即形式为y ax^2 bx c的方程)。然后,我们可以使用matplotlib来绘制散点图,并在图上添加最佳拟…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...