网络编程

程序员主要操作应用层和传输层来实现网络编程,也就是自己写一个程序,让这个程序可以使用网络来通信,这个程序属于应用层,实现通讯就需要获取到传输层提供的服务
这就需要使用传输层提供的api

UDP: 无连接,不可靠传输,面向数据报,全双工
TCP:  有连接,可靠传输,面向字节流,全双工

接下来介绍着四个点↓

连接

这里的连接是个抽象的概念
比如两个人领证了才算结婚,这时候就相当于把两个人连接起来了,但是这个连接不是拿绳子拴着,是通过过结婚证那个小本本来把两个人连接起来的(一对一)
客户端和服务器之间,使用这个小本本(内存)保存对应的端口号的信息,双方都保存了这个信息,此时“连接”就出现了,TCP是有连接的,也是基于这种方式实现的
这里最大的区别在于,一个客户可以连接多个服务器,一个服务器也可以多对应多个客户(多对多)(比如一个人可以去多个餐馆买今天的晚饭,一个餐馆也可以接待多个客人)

可靠传输

可靠传输不是说的是 A给B发的消息百分百能到,而是,A尽可能的把消息传给B,并且在传输失败的时候,A能感知到,或者在传输成功的时候,也能知道自己传输成功了
有舍才有得,既然TCP是可靠传输,那么它的传输效率就降低了有人会问了,既然TCP是可靠传输,UDP是不可靠的,那么TCP是不是比UDP安全呢?
当然不是!!!可靠不等于安全!!!
“网络安全”指的是你传输的数据是否容易被黑客或其他有心之人截获,以及如果截获后是否会泄露一些重要信息

面向字节流和面向数据报

TCP是面向字节流,它的字节流和文件操作类似,都是“流”式的(由于这里传输的单位是字节,所以称为字节流)跟水流一样,假如通过tcp读写100字节的数据,可以一次读写100字节,也可以一次读写50字节,分两次,还可以一次读写10字节,分10次
UDP是面向数据报,UDP读写的基本单位,是一个UDP数据报,这个数据报包含了一系列的数据和属性

 全双工和半双工

全双工,一个通道,可以双向通信
半双工,一个通道,只能单向通信
网线就是全双工呢,一根网线包含八根铜缆,一组里面有的负责这个方向,有的负责那个方向

 为什么需要网络编程?

用户在浏览器中,打开在线视频网站,如爱奇艺看视频,实质是通过网络,获取到网络上的一个视频资源。与本地打开视频文件类似,只是视频文件这个资源的来源是网络。相比本地资源来说,网络提供了更为丰富的网络资源,所谓的网络资源,其实就是在网络中可以获取的各种数据资源。而所有的网络资源,都是通过网络编程来进行数据传输的。你现在所看的这篇博客也是网络传输的资源

什么是网络编程?

网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。当然,我们只要满足进程不同就行;所以即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程。特殊的,对于开发来说,在条件有限的情况下,一般也都是在一个主机中运行多个进程来完成网络编程。但是,我们一定要明确,我们的目的是提供网络上不同主机,基于网络来传输数据资源:
进程A:编程来获取网络资源 (客户端)
进程B:编程来提供网络资源 (服务端)

网络编程中的基本概念

发送端和接收端

在一次网络数据传输时:
发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机。
接收端:数据的接收方进程,称为接收端。接收端主机即网络通信中的目的主机。


注意:发送端和接收端只是相对的,只是一次网络数据传输产生数据流向后的概念。

 请求和响应

 一般来说,获取一个网络资源,涉及到两次网络数据传输:
第一次:请求数据的发送
第二次:响应数据的发送。


请求数据先由客户端发送给服务器,响应经过服务器的处理再返回客户端

 服务端和客户端

服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务。
客户端:获取服务的一方进程,称为客户端。
 

常见的客户端服务端模型

最常见的场景,客户端是指给用户使用的程序,服务端是提供用户服务的程序:

  1. 客户端先发送请求到服务端
  2. 服务端根据请求数据,执行相应的业务处理
  3. 服务端返回响应:发送业务处理结果
  4. 客户端根据响应数据,展示处理结果(展示获取的资源,或提示保存资源的处理结果)

 Socket套接字

什么是套接字?

Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程

分类 

 Socket套接字主要针对传输层协议划分为如下三类
流套接字:使用传输层TCP协议TCP,即Transmission Control Protocol(传输控制协议),传输层协议
数据报套接字:使用传输层UDP协议UDP,即User Datagram Protocol(用户数据报协议),传输层协议
原始套接字:原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据.(用的较少)

 UDP数据报套接字编程

DatagramSocket API

这个类是一个Socket对象(基于UDP协议)
操作系统使用文件这样的概念来管理一些软硬件资源,同样的操作系统也是用文件的方式来管理网卡的,表示网卡这类的文件称为Socket文件。(假如你把键盘插入到电脑上,操作系统也认为是一个键盘文件)java中Socket对象来表示系统的Socket文件,系统的Socket文件来表示网卡,最终还是要落到网卡身上,毕竟进行网络通信,绕不开网卡这样的设备,因此要想进行网络通信,必须要有Socket对象,Socket对象关联Socket文件,Socket文件关联网卡,最终通过网卡来使我们实现网络通讯,来实现发送数据和接收数据

 

 客户端使用系统分配的端口号原因可能是客户端像发送程序2的请求,但是如果你想手动指定一个18号端口,可能这个端口会被程序1占着呢,对于服务器来说,手动设定一个固定窗口,方便其他客户找到

 

 receive相当于读,send相当于写

DatagramPacket API

 这个类表示了一个UDP数据报,是UDPSocket发送和接收的数据报。代表了系统中设定的UDP数据报的二进制结构

构造UDP发送的数据报时,需要传入SocketAddress ,该对象可以使用 InetSocketAddress 来创建。

 

 

回显服务器(echo server)

回显服务器是一个最简单的服务器,也就是客户端发啥,服务器返回啥,没有经过服务器的复杂的逻辑运算(企业中这里是重中之重)

服务器代码

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 {// 创建一个 DatagramSocket 对象,用于发送和接收 UDP 数据报//指定一个固定端口号, 让服务器来使用socket = new DatagramSocket(port);}public void start() throws IOException {//启动服务器System.out.println("服务器启动成功: ");// 循环接收数据报while (true) {//循环一次就相当于处理了一次请求//处理请求的过程,典型的服务器都分成三个步骤://1.读取请求并解析// DatagramPacket 表示一个 UDP 数据报, 此处传入的字节数组,就保存UDP的载荷部分DatagramPacket requestPackage = new DatagramPacket(new byte[4096], 4096);socket.receive(requestPackage);//把读取的二进制数据 转换成字符串 只构造有效部分String request = new String(requestPackage.getData(), 0, requestPackage.getLength());//2.根据请求 计算响应(服务器关键逻辑)//此处是写的是回显(Echo)服务器, 这个处理环节就相当于省略了String response = process(request);//用方法封装处理逻辑//3.发送响应到客户端//根据response构造一个新的 DatagramPacket包, 并发送给客户端//此处不能使用response.getlength(),因为response可能包含中文字符,会导致长度不一致,导致发送失败(因为长度不匹配)DatagramPacket responsePackage = new DatagramPacket(response.getBytes(), response.getBytes().length,requestPackage.getSocketAddress());//或的端口号和IP地址//此处不能直接发送 UDP协议自身没有保存对方的地址信息和端口号(不知道发给谁)//需要指定的目的ip和端口号socket.send(responsePackage);//4.打印一个日志System.out.printf("[%s:%d] req: %s, resq: %s\n", requestPackage.getAddress().toString(), requestPackage.getPort(),request, response);}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer udpEchoServer = new UdpEchoServer(9090);udpEchoServer.start();}
}

 

 

 

 

 客户端代码

import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;//UDP不保存对端的信息,就需要自己的代码中保存一下private String serverIp;private int serverPort;public UdpEchoClient(String serverIp, int serverPort) throws SocketException {this.serverIp = serverIp;this.serverPort = serverPort;socket = new DatagramSocket();}public void start() throws IOException{Scanner scanner = new Scanner(System.in);while (true) {//1,从控制台中读取用户输入的内容System.out.println("请输入要发送的内容: ");if (!scanner.hasNext()) {break;}String request = scanner.next();//2.把请求发送给服务器, 需要构造出DatagramPacket对象,包含请求内容和服务器的地址和端口DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,InetAddress.getByName(serverIp), serverPort);//3.发送请求socket.send(requestPacket);//4.接收服务器的响应DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);socket.receive(responsePacket);//5.从服务器读取的数据进行解析, 打印出来String response = new String(responsePacket.getData(), 0, responsePacket.getLength());System.out.println(response);}}public static void main(String[] args) throws IOException {UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1", 9090);//“127.0.0.1”是本机IP地址 是一个特殊的IP地址,它表示本机回环地址,它唯一的作用就是作为一个本地地址来使用 类似于this的作用//无论主机的ip是多少都可以用回环地址来表示本机的ipudpEchoClient.start();}}

 

127.0.0.1指的是本机IP

 执行流程↓

TCP流套接字编程 

tcp是面向字节流的,是一个字节一个字节进行传输的,一个tcp数据报,就是一个字节数组(byte[]),因此并不像udp一样,需要一个特定的类来代表tcp字节流

ServerSocket API

ServerSocket 是创建TCP服务端Socket的API。 是给服务器用的

 

Socket API 

服务器和客户端都可以用

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。
不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

 回显服务器

服务器代码

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class TcpEchoServer {private ServerSocket serverSocket = null;public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动");//这种情况一般不会使用 fixedThreadPool 意味着同时处理的客户端连接数目就固定了 企业级会有上千万甚至亿的客户端来访问ExecutorService executorService = Executors.newCachedThreadPool();while (true) {//tcp来说,需要先处理客户端发来的请求//通过写clientSocket 和客户端进行通信//如果没有客户端发来连接,则会一直阻塞在accept()方法上Socket clientSocket = serverSocket.accept();//将任务提交给线程池executorService.submit(() -> {procrssConnection(clientSocket);});}}private void procrssConnection(Socket clientSocket) {System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress(), clientSocket.getPort());try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()){//针对InputStream套了个Scanner,可以方便的读取请求//作用就是从输入流中读取数据,并按行分割Scanner scanner = new Scanner(inputStream);//针对OutputStream套了个PrintWriter,可以方便的发送响应//作用就是把数据写到输出流中,并刷新缓冲区PrintWriter printWriter = new PrintWriter(outputStream);//分成三步骤while (true) {//1.读取请求并解析,可以直接read,也可以借助scanner来辅助完成if (!scanner.hasNext()) {//连接断开break;}String request = scanner.next();//2.根据请求计算响应String response = process(request);//3.发送响应到客户端//outputStream.write(response.getBytes());printWriter.println(response);printWriter.flush();//打印日志System.out.printf("[%s:%d] req:%s, resp: %s\n", clientSocket.getInetAddress(), clientSocket.getPort(), request, response);}} catch (IOException e) {e.printStackTrace();} finally {try {//关闭客户端连接//防止多个客户端占满服务器资源clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}}

 

 

 客户端代码

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoCilent {private Socket socket = null;public TcpEchoCilent(String serverIp, int serverPort) throws IOException {//直接设置服务器地址和端口socket = new Socket(serverIp, serverPort);}public void start() {try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scanner = new Scanner(System.in);//为了使用方便,套壳操作Scanner scannerNet = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);while (true) {//1.从控制台读取请求输入String request = scanner.next();//2.发送请求到服务器printWriter.println(request);//刷新缓冲区才是真正的发送数据printWriter.flush();//3.读取服务器返回的响应String response = scannerNet.next();//4。打印到控制台System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoCilent cilent = new TcpEchoCilent("127.0.0.1", 9090);cilent.start();}}

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

claude-code订阅方案

Claude Code 订阅方案对比 编写日期:2025 年 08 月 20 日 🏷️ 专业版 Pro ($20/月,$200/年) 主要特性 可用模型:Claude Sonnet 4(Claude Opus 4成本太高,谨慎选择)适用场景:适合轻度…

146. LRU缓存

题目: 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值&#x…

第二十节:3D文本渲染 - 字体几何体生成与特效

第二十节:3D文本渲染 - 字体几何体生成与特效 TextGeometry深度解析与高级文字效果实现1. 核心概念解析 1.1 3D文字渲染技术对比技术原理优点缺点TextGeometry将字体轮廓转换为3D网格真实3D效果,支持材质性能开销大,内存占用高Canvas纹理将文…

zzz‘sJava知识点概括总结

类型转化 字符串&#xff1a;c语言&#xff1a;char Java&#xff1a;string 表达式值的类型由最高类型决定&#xff1a; 取值范围&#xff1a;byte<short<int<long<float<double&#xff08;且运算时byte和short都是转化为int类型进行计算防止数据溢出&…

SONiC 之 Testbed(2)Ansible

Ansible 是一款由 Red Hat 主导开发的 开源自动化工具&#xff0c;专注于 配置管理、应用部署、任务编排和IT自动化。它基于 无代理&#xff08;Agentless&#xff09;架构&#xff0c;通过 SSH&#xff08;默认&#xff09;或 WinRM 协议与目标设备通信&#xff0c;无需在被控…

瑞芯微RK3568与君正X2600e平台Linux系统CS创世SD NAND应用全解析与驱动架构详解

前言 今天就瑞芯微平台和北京君正平台下的linux系统中关于CS创世 SD NAND的使用做一些经验的分享&#xff0c;如有不正&#xff0c;请批评指正&#xff1b; 采用的开发板是RK3568和x2600e&#xff0c;ubuntu版本是20.04&#xff0c;交叉编译工具链是aarch64-linux-gnu-和mips…

深入解析 Flink Function

RichFunctionFunction只是个标记接口public interface Function extends java.io.Serializable {}RichFunction 的核心语义是为用户定义的函数&#xff08;UDF&#xff09;提供生命周期管理和运行时上下文访问的能力。任何一个普通的 Flink Function 接口&#xff08;例如 MapF…

JMeter —— 压力测试

目录 常用的性能指标 一、吞吐量类指标 二、响应时间类指标 三、资源利用率指标 JMeter 一、JMeter 简介 二.下载安装JMeter&#xff1a; 三.如何使用JMeter&#xff1a; 压力测试考察当前软硬件环境下系统所能承受的最大负荷并帮助找出系统瓶颈所在。压测都是为了系统…

Transformer在哪⾥做了权重共享?

1、什么是权值共享权重共享是指在模型的不同层之间复⽤相同的参数。这可以减少模型的总体参数数量&#xff0c;并使得模型在训练时更容易学习。2、在Transformer中的应用常见的做法是共享词嵌入层&#xff08;embedding layer&#xff09;和输出层&#xff08;output layer&…

将 agents 连接到 Elasticsearch 使用模型上下文协议 - docker

我们在之前的文章 “将 agents 连接到 Elasticsearch 使用模型上下文协议” 及 “使用 MCP 将代理连接到 Elasticsearch 并对索引进行查询” 详述了如何使用 Elasticsearch MCP server 来和我们的 Elasticsearch 进行对话。细心的开发者可能已经注意到我们的 Elasticsearch MCP…

Shell 编程基础与实践要点梳理

目录 前言 一、认识 Shell 1.1 Shell 的定义与作用 1.2 Shell 解释器 二、Shell 脚本入门 2.1 编写 Shell 脚本 2.2 赋予执行权限与执行脚本 三、Shell 变量 3.1 变量定义与规则 3.2 变量使用与操作 3.3 变量类型 四、Shell 字符串 4.1 字符串定义方式 4.2 字符串…

Python自动化测试完整教程:pytest + selenium实战

目录 前言环境搭建pytest基础教程selenium基础教程pytest selenium实战项目页面对象模式(POM)测试报告生成持续集成配置最佳实践和进阶技巧总结 前言 自动化测试是现代软件开发中不可或缺的一环。Python作为一门简洁优雅的编程语言&#xff0c;配合pytest测试框架和seleniu…

APM 系列(一):Skywalking 与 Easyearch 集成

概述 SkyWalking 是一个开源的可观测性平台&#xff0c;用于收集、分析、聚合和可视化服务和云原生基础设施的数据。SkyWalking 提供了一种简单的方法&#xff0c;即使在云之间也能保持对分布式系统的清晰视图。它是一个现代的 APM&#xff0c;专门为云原生、基于容器的分布式…

使用 AD 帐户从 ASP.NET 8 容器登录 SQL Server 的 Kerberos Sidecar

我最近在做一个项目,需要将一个 ASP.NET 8 Web API 应用程序容器化,该应用程序需要与本地运行的 SQL Server 数据库进行通信。我们决定将 ASP.NET 8 容器定位到 Linux 系统,因此必须与运行在 Windows AD 域中的数据库进行通信。 问题 我们之前的设置是使用 IIS 在 Windows …

More Effective C++ 条款11:禁止异常流出析构函数之外

More Effective C 条款11&#xff1a;禁止异常流出析构函数之外核心思想 在C中&#xff0c;析构函数绝对不允许抛出异常。如果异常从析构函数中传播出去&#xff0c;可能会导致程序立即终止或未定义行为&#xff0c;特别是在栈展开过程中处理已有异常时。通过捕获并处理所有析构…

商超高峰客流统计误差↓75%!陌讯多模态融合算法在智慧零售的实战解析

原创声明&#xff1a;本文为原创技术解析&#xff0c;核心技术参数、架构设计及实战数据引用自 “陌讯技术白皮书”&#xff0c;技术方案与落地案例结合aishop.mosisson.com智慧零售数据联动场景展开&#xff0c;禁止未经授权的转载与商用。 一、行业痛点&#xff1a;智慧零售…

PyTorch实战(2)——使用PyTorch构建神经网络

PyTorch实战&#xff08;2&#xff09;——使用PyTorch构建神经网络0. 前言1. PyTorch 构建神经网络初体验1.1 使用 PyTorch 构建神经网络1.2 神经网络数据加载1.3 模型测试1.4 获取中间层的值2. 使用 Sequential 类构建神经网络3. PyTorch 模型的保存和加载3.1 模型保存所需组…

关于git的安装(windows)

1.git的介绍 Git 是一个分布式版本控制系统&#xff0c;由 Linus Torvalds 在 2005 年为 Linux 内核开发而创建。它能够高效地处理从小型到超大型项目的版本管理&#xff0c;具有以下特点&#xff1a; 分布式架构&#xff1a;每个开发者本地都有完整的仓库副本高效性能&#…

Java后端开发?接口封装器!

开发接口确实是Java后端开发中最核心、最可见的产出工作。“对入参校验、处理业务逻辑、返回格式处理”——精准地描述了一个API接口的核心处理流程。 但这只是冰山之上最直观的部分。一个专业、稳健、可扩展的后端系统&#xff0c;其复杂性和价值绝大部分隐藏在冰山之下。结合…

【沉浸式解决问题】NVIDIA 显示设置不可用。 您当前未使用连接到NVIDIA GPU 的显示器。

目录一、问题描述二、环境版本三、原因分析四、解决方案一、问题描述 在看一篇cuda安装的教程时&#xff0c;第一步是打开NVIDIA 控制面板&#xff0c;但是我打不开&#xff1a; NVIDIA 显示设置不可用。 您当前未使用连接到NVIDIA GPU 的显示器。 二、环境版本 设备&#xf…