OkHttp: 使用入门

文章目录

    • 1. 领域对象
      • 1. Request
      • 2. Response
        • 2.1 请求重写
        • 2.2 重写返回
        • 2.3 跟踪请求
        • 2.4 自动重试
      • 3. Calls
    • 2. 创建连接
      • 1、URLs
      • 2、Addresses
      • 3、Routes
      • 4、Connections
    • 3. 使用案例
      • 1、同步GET请求
      • 2、异步GET请求
      • 3、发送和读取HTTP头
      • 4、POST 字符传
      • 5、POST 流
      • 6、POST 文件内容
      • 7、POST 表单
      • 8、上传
      • 9、使用Moshi在JSON和对象之间转换
      • 10、缓存Response
      • 11、取消Call调用
      • 12、超时
      • 13、设置
      • 14、Authentication
      • 15. 设置代理

1. 领域对象

HTTP客户端的作用就是接受你的请求,获取对应的返回。理论上简单的,然后实践过程会有一些陷阱。OkHttp是其中使用的比较广泛的一个。

okhttp主要包含的概念如下:

1. Request

包含请求的url,方法(GET/POST/PUT等待),HTTP头,以及请求体。

2. Response

返回的编码(200 成功, 404 页面不存在),HTTP头,以及返回体。

2.1 请求重写

我们会在高层次的描述请求哪个地址,包含什么头等等。为了正确性和高效,OkHttp会帮我们重写请求。

  • 添加缺失的HTTP头,包括Content-Lenght、Transfer-Encoding、User-Agent、Host、Connection、Content-Type
  • 动添加一个Accept-Encoding,支持自动解压gzip等压缩过的返回
  • 如果你有Cookie,OkHttp会自动添加一个Cookie的HTTP头
  • 可缓存的请求(Cache-Control、Expired、Etag等),自动添加If-Modified-Since、If-None-Match头
2.2 重写返回
  • 如果返回是压缩过的,OkHttp会自动解压,并删除Content-Encoding和Content-Length头,因为这两个值解压后已经不准确
  • 如果是条件获取(If-Modified-Since等),OkHttp会自动切换从本地缓存或者服务端获取内容
2.3 跟踪请求
  • 自动完成302跳转,获取最终结果页面内容
  • 如果配置了Authenticator,自动HTTP权限验证
2.4 自动重试
  • 连接池内连接过期或者服务器不可触达,尝试重试(重试的机制还需要深挖)

3. Calls

由于请求重写、跟踪请求、自动重试等等,你描述的请求实际上会产生多个Request/Response, OkHttp将这个操作抽象为一个Call。
Call实际上有两种执行方式

  • 同步执行,当前线程阻塞,指定请求完成
  • 异步执行,当前请求如队列,完成请求会回调注册的接口

Call可以被其他线程取消。如果Call被取消后还有线程还有代码去写Request或者读Response会抛出IOException

在同步模式下,你使用自己线程,并负责管理simultaneous,太多的simultaneous connections浪费资源,过少则影响延时
在异步模式下,Dispatcher负责管理simultaneous,你可以设置每个webserver(默认5个)以及总(默认64个)的连接数。

2. 创建连接

尽管你只提供一个URL链接,OkHttp会使用三种类型去链接WebServer,它们分别是: URL、Address、Route

1、URLs

URL是HTTP和互联网的基础,处理提供Web上资源的统一命名服务,同样指定了怎么访问Web资源。

URL是抽象的

  • 指定了请求内容是纯文本(http)还是加密的(https)
  • 没有指定加解密算法,怎么去验证证书(HostnameVerifier),哪些证书是可靠的(SSLSocketFactory)
  • 没有指定怎么使用代理服务器,以及代理服务器怎么鉴权

2、Addresses

Adress指定了一个WebServer,包括所有连接服务器所需要的信息(包括端口、HTTPS设置、倾向的网络协议,如HTTP/2、SPDY等)。

相同服务器地址的URL可能会共享底层的TCP连接,共享TCP连接会有明显的性能优势:

  • 更低延迟
  • 更高吞吐量(TCP慢启动)
  • 省电

OkHttp通过ConnectionPool自动重用连接。

3、Routes

Routes提供了自动链接WebServer里的必要信息,包括

  • IP地址,通过DNS获取
  • 确定的代理服务器,如果配置了ProxySelector的话
  • TLS(传输层安全协议)版本号

一个Adress可能会有多个Routes,比如一个跨数据中心部署的WebServer,DNS解析后肯能会有多个地址。

4、Connections

当你请求URL时,OkHttp为你做了以下操作:

  1. 使用URL和配置好的OkHttpClient创建一个Addresss,里边包含了我们怎么去连接Web服务器的信息。
  2. 尝试从ConnectionPool里获取一个对应Address的连接。
  3. 找不到连接的话,它会尝试选择一个Route,这意味着DNS解析、选择TLS版本以及代理服务器(需要的话)。
  4. 如果这是一个新的Route,它会创建一个Socket连接、TLS隧道(经过HTTPS的代理服务)、TLS连接。如果需要的话,完成TLS握手。
  5. 发生请求并读取结果。

如果连接有问题的话,OkHttp会重新选择另外一个Route并重试。这有助于OkHttp从服务端部分地址不可用时恢复。同样有助于当连接过期,或者TLS版本不支持的时候。

当响应读取完成后,连接会被退回到连接池中等待重用,一段时间没有使用后会被从连接池里清除。

3. 使用案例

我们提供了一下用OkHttp解决常见问题的样例。

1、同步GET请求

当响应结果比较小的时候(<1M),response.body().string()是方便且高效的,否则应该使用流读取。

  private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {Request request = new Request.Builder().url("https://publicobject.com").build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);Headers responseHeaders = response.headers();for (int i = 0; i < responseHeaders.size(); i++) {System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));}System.out.println(response.body().string());}}

2、异步GET请求

在OkHttp的工作线程里请求,当响应可读的时候调用回调函数。回调函数实在响应HTTP头读取后调用的,读取响应体还是需要同步完成。

private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {Request request = new Request.Builder().url("http://publicobject.com").build();client.newCall(request).enqueue(new Callback() {@Override public void onFailure(Call call, IOException e) {e.printStackTrace();}@Override public void onResponse(Call call, Response response) throws IOException {try (ResponseBody responseBody = response.body()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);Headers responseHeaders = response.headers();for (int i = 0, size = responseHeaders.size(); i < size; i++) {System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));}System.out.println(responseBody.string());}}});}

3、发送和读取HTTP头

一般来说,HTTP头一个KEY会对应一个值,但是有的字段允许有多个值。OkHttp为这两种情况提供了支持:

  • Request.Builder.header(name,value)方法,支持单值的HTTP头,把已存在的同名HTTP头删除。
  • Request.Builder.addHeader(name,value)只是单纯的添加,不会有删除操作。
  • Response.header(name),获取多值的最后一个,没有的话返回null。
  • Response.headers(name),返回多值
 private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {Request request = new Request.Builder().url("https://api.github.com/repos/square/okhttp/issues").header("User-Agent", "OkHttp Headers.java").addHeader("Accept", "application/json; q=0.5").addHeader("Accept", "application/vnd.github.v3+json").build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);System.out.println("Server: " + response.header("Server"));System.out.println("Date: " + response.header("Date"));System.out.println("Vary: " + response.headers("Vary"));}}

4、POST 字符传

 public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {String postBody = "* _1.2_ August 11, 2013\n";Request request = new Request.Builder().url("https://api.github.com/markdown/raw").post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody)).build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);System.out.println(response.body().string());}}

5、POST 流

使用流做为请求体,请求体内容会在发送请求的时候输出,这个例子里使用的是Okio的BufferedSink,你也可以通过BufferedSkin.outputStream获取输出流。

  public static final MediaType MEDIA_TYPE_MARKDOWN= MediaType.parse("text/x-markdown; charset=utf-8");private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {RequestBody requestBody = new RequestBody() {@Override public MediaType contentType() {return MEDIA_TYPE_MARKDOWN;}@Override public void writeTo(BufferedSink sink) throws IOException {sink.writeUtf8("Numbers\n");sink.writeUtf8("-------\n");for (int i = 2; i <= 997; i++) {sink.writeUtf8(String.format(" * %s = %s\n", i, 2*i));}}};Request request = new Request.Builder().url("https://api.github.com/markdown/raw").post(requestBody).build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);System.out.println(response.body().string());}}

6、POST 文件内容

  public static final MediaType MEDIA_TYPE_MARKDOWN= MediaType.parse("text/x-markdown; charset=utf-8");private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {File file = new File("README.md");Request request = new Request.Builder().url("https://api.github.com/markdown/raw").post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file)).build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);System.out.println(response.body().string());}}

7、POST 表单

  private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {RequestBody formBody = new FormBody.Builder().add("search", "Jurassic Park").build();Request request = new Request.Builder().url("https://en.wikipedia.org/w/index.php").post(formBody).build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);System.out.println(response.body().string());}}

8、上传

  private static final String IMGUR_CLIENT_ID = "...";private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/imageRequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("title", "Square Logo").addFormDataPart("image", "logo-square.png",RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png"))).build();Request request = new Request.Builder().header("Authorization", "Client-ID " + IMGUR_CLIENT_ID).url("https://api.imgur.com/3/image").post(requestBody).build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);System.out.println(response.body().string());}}

9、使用Moshi在JSON和对象之间转换

Moshi是一个简便的JSON转换类库。
ResponseBody.charStream()使用Content-Type里的编码解释响应内容,找不到编码默认UTF-8。

  private final OkHttpClient client = new OkHttpClient();private final Moshi moshi = new Moshi.Builder().build();private final JsonAdapter<Gist> gistJsonAdapter = moshi.adapter(Gist.class);public void run() throws Exception {Request request = new Request.Builder().url("https://api.github.com/gists/c2a7c39532239ff261be").build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);Gist gist = gistJsonAdapter.fromJson(response.body().source());for (Map.Entry<String, GistFile> entry : gist.files.entrySet()) {System.out.println(entry.getKey());System.out.println(entry.getValue().content);}}}static class Gist {Map<String, GistFile> files;}static class GistFile {String content;}

10、缓存Response

要缓存Response,你需要一个可以读写的目录,以及设置缓存的大小。 大多数应用只需要创建一次OkHttpClient对象,两个实例使用同一个缓存目录会导致冲突,甚至使程序崩溃。
Response缓存通过服务端HTTP头控制。
添加一下HTTP头可以控制缓存的行为:

  • CacheControl.FORCE_NETWORK,强制从服务端加载。
  • CacheControl.FORCE_CACHE,强制从缓存加载,当缓存中信息不可获取(不存在或者过期),返回504
 private final OkHttpClient client;public CacheResponse(File cacheDirectory) throws Exception {int cacheSize = 10 * 1024 * 1024; // 10 MiBCache cache = new Cache(cacheDirectory, cacheSize);client = new OkHttpClient.Builder().cache(cache).build();}public void run() throws Exception {Request request = new Request.Builder().url("http://publicobject.com/helloworld.txt").build();String response1Body;try (Response response1 = client.newCall(request).execute()) {if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);response1Body = response1.body().string();System.out.println("Response 1 response:          " + response1);System.out.println("Response 1 cache response:    " + response1.cacheResponse());System.out.println("Response 1 network response:  " + response1.networkResponse());}String response2Body;try (Response response2 = client.newCall(request).execute()) {if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);response2Body = response2.body().string();System.out.println("Response 2 response:          " + response2);System.out.println("Response 2 cache response:    " + response2.cacheResponse());System.out.println("Response 2 network response:  " + response2.networkResponse());}System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));}

11、取消Call调用

通Call.cancel()取消调用,如果另外一个线程正在写请求或者读取返回时,抛出IOException

  private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {Request request = new Request.Builder().url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay..build();final long startNanos = System.nanoTime();final Call call = client.newCall(request);// Schedule a job to cancel the call in 1 second.executor.schedule(new Runnable() {@Override public void run() {System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f);call.cancel();System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f);}}, 1, TimeUnit.SECONDS);System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f);try (Response response = call.execute()) {System.out.printf("%.2f Call was expected to fail, but completed: %s%n",(System.nanoTime() - startNanos) / 1e9f, response);} catch (IOException e) {System.out.printf("%.2f Call failed as expected: %s%n",(System.nanoTime() - startNanos) / 1e9f, e);}}

12、超时

当端不可触达的时候,客户端连接问题、服务端不可用、或者两者之间的问题,可以通过设置超时。OkHttp支持三种超时: 连接超时,写请求超时,读返回超时。

  private final OkHttpClient client;public ConfigureTimeouts() throws Exception {client = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).build();}public void run() throws Exception {Request request = new Request.Builder().url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay..build();try (Response response = client.newCall(request).execute()) {System.out.println("Response completed: " + response);}}

13、设置

所有的设置都是通过OkHttpClient完成的,包括代理、超时、缓存等等。当你需要为一个请求修改设置的时候,调用OkHttpClient.builder()方法,返回的builder和原始的OkHttpClient共享连接池、Dispatcher和配置信息,只需要修改特有的配置即可。

 private final OkHttpClient client = new OkHttpClient();public void run() throws Exception {Request request = new Request.Builder().url("http://httpbin.org/delay/1") // This URL is served with a 1 second delay..build();// Copy to customize OkHttp for this request.OkHttpClient client1 = client.newBuilder().readTimeout(500, TimeUnit.MILLISECONDS).build();try (Response response = client1.newCall(request).execute()) {System.out.println("Response 1 succeeded: " + response);} catch (IOException e) {System.out.println("Response 1 failed: " + e);}// Copy to customize OkHttp for this request.OkHttpClient client2 = client.newBuilder().readTimeout(3000, TimeUnit.MILLISECONDS).build();try (Response response = client2.newCall(request).execute()) {System.out.println("Response 2 succeeded: " + response);} catch (IOException e) {System.out.println("Response 2 failed: " + e);}}

14、Authentication

OkHttp会自动重试未授权的请求,当服务端返回401的时候,OkHttp会尝试寻找Authenticator注册信息,如果有的话通过对应信息进行验证。代码关键点:

  • response.challenges()
  • Credentials.basic
  • response.request().newBuilder()
  private final OkHttpClient client;public Authenticate() {client = new OkHttpClient.Builder().authenticator(new Authenticator() {@Override public Request authenticate(Route route, Response response) throws IOException {if (response.request().header("Authorization") != null) {return null; // Give up, we've already attempted to authenticate.}System.out.println("Authenticating for response: " + response);System.out.println("Challenges: " + response.challenges());String credential = Credentials.basic("jesse", "password1");return response.request().newBuilder().header("Authorization", credential).build();}}).build();}public void run() throws Exception {Request request = new Request.Builder().url("http://publicobject.com/secrets/hellosecret.txt").build();try (Response response = client.newCall(request).execute()) {if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);System.out.println(response.body().string());}}

Authenticator返回null的时候,OkHttp会停止重试。为了避免Authentication不起效时还反复重试, 可以再重试过一次之后,返回null退出执行

  if (credential.equals(response.request().header("Authorization"))) {return null; // If we already failed with these credentials, don't retry.}

你以可以通过Response.priorResponse()来计数调用了多少次,次数满是退出重试。

  if (responseCount(response) >= 3) {return null; // If we've failed 3 times, give up.}private int responseCount(Response response) {int result = 1;while ((response = response.priorResponse()) != null) {result++;}return result;}

15. 设置代理

Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1",12345));
OkHttpClient client = new OkHttpClient.Builder().proxy(proxy).build();Request request = new Request.Builder().url(url).header("Authorization", signature).post(RequestBody.create(MEDIA_JSON, postBody)).build();
Response response = client.newCall(request).execute();

 
 
 

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

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

相关文章

mysql 字符串合并方法以及合并为null问题

concat()不推荐 mysql一般提供了两种一种是concat()函数一种是concat_ws()函数&#xff0c;前者合并字符串有个弊端&#xff0c;合并字段不能有null值&#xff0c; 否则如下图合并后会是null concat_ws()推荐 concat_ws()函数可以解决合并字符串为null问题&#xff0c;conca…

Go并发编程:保障安全与解锁奥秘

一、并发安全与锁 1、并发安全 有时候在 Go 代码中可能会存在多个 goroutine 同时操作一个资源&#xff08;临界区&#xff09;&#xff0c;这种情况会发生竞态问题&#xff08;数据竞态&#xff09;类比现实生活中的例子有十字路口被各个方向的汽车竞争&#xff1b;还有火车…

使用Microsoft Dynamics AX 2012 - 8. 财务管理

财务管理的主要职责是控制和分析与货币金额有关的所有交易。这些事务发生在整个组织的业务流程中。 因此&#xff0c;财务管理是企业管理解决方案的核心领域。在Dynamics AX中&#xff0c;支持所有部门业务流程的应用程序的深度集成可立即提供准确的财务数据。 分类账交易的原…

K8S(三)—组件

目录 k8s组件控制平面组件&#xff08;Control Plane Componentskube-apiserveretcdkube-schedulerkube-controller-managercloud-controller-managerNode 组件kubelet&#xff08;单独的进程&#xff09;kube-proxy&#xff08;单独的进程&#xff09;容器运行时&#xff08;C…

Redis常问面试题

Redis常问面试题 Redis常问面试题1、Redis 支持哪几种数据类型&#xff1f;2、Redis 做登录是怎么实现的&#xff1f;和传统session有何区别&#xff1f;3、什么是缓存穿透&#xff1f;4、什么是缓存雪崩&#xff1f;5、什么是缓存击穿&#xff1f;6、Redis高可用的几种实现方式…

12.13每日一题(备战蓝桥杯快速排序)

12.13每日一题&#xff08;备战蓝桥杯快速排序&#xff09; 题目 快速排序 给定你一个长度为 n 的整数数列。 请你使用快速排序对这个数列按照从小到大进行排序。 并将排好序的数列按顺序输出。 输入格式 输入共两行&#xff0c;第一行包含整数 n。 第二行包含 n 个整数&…

MySQL 中Relay Log打满磁盘问题的排查方案

MySQL 中Relay Log打满磁盘问题的排查方案 引言&#xff1a; MySQL Relay Log&#xff08;中继日志&#xff09;是MySQL复制过程中的一个重要组件&#xff0c;它用于将主数据库的二进制日志事件传递给从数据库。然而&#xff0c;当中继日志不断增长并最终占满磁盘空间时&…

实操Nginx(4层代理+7层代理)+Tomcat多实例部署,实现负载均衡和动静分离

目录 前言 一、tomcat多实例部署 步骤一&#xff1a;先安装jdk&#xff0c;设置jdk的环境变量&#xff0c;验证是否安装完成&#xff08;192.168.20.8&#xff09; 步骤二&#xff1a;安装tomcat&#xff08;192.168.20.18&#xff09; 步骤三&#xff1a;安装tomcat多实例…

快速上手linux | 一文秒懂Linux各种常用目录命令(上)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 一 、命令提示符和命令的基本格式1.1 如何查看主机名称及修改 二、命令基本格式2.1 命令格式示例2.2 参数的作用…

Spring Cloud gateway - CircuitBreaker GatewayFilte

前面学习Spring cloud gateway的时候&#xff0c;做测试的过程中我们发现&#xff0c;Spring Cloud Gateway不需要做多少配置就可以使用Spring Cloud LoadBalance的功能&#xff0c;比如&#xff1a; spring:application:name: spring-gatewaycloud:gateway:routes:- id: path…

java并发-ReentrantReadWriteLock读写锁

文章目录 介绍读写锁的获取规则示例源码解读ReentrantReadWriteLock核心变量ReentrantReadWriteLock相关属性和构造函数Sync静态内部类的核心属性tryAcquireShared方法tryAcquire方法锁降级 总结 介绍 读写锁就是将一个锁拆分为读锁和写锁两个锁。 读写锁的获取规则 如果有一…

33KB代码实现短网址(php+mysql) V2.0

查立得短网址 V2.0 请保留署名信息;请勿用于非法用途 系统简述&#xff1a;三五十KB代码实现短网址功能前后端都登陆,相对第一版代码已重构。 开发环境&#xff1a;宝塔:linux php Nginx 7.1/mysql5.6;建议环境&#xff1a;linux php 5.4-7.3; 空间域名&#xff1a;域名解析到对…

ELK简单介绍二

学习目标 能够部署kibana并连接elasticsearch集群能够通过kibana查看elasticsearch索引信息知道用filebeat收集日志相对于logstash的优点能够安装filebeat能够使用filebeat收集日志并传输给logstash kibana kibana介绍 Kibana是一个开源的可视化平台,可以为ElasticSearch集群…

电子取证中Chrome各版本解密Cookies、LoginData账号密码、历史记录

文章目录 1.前置知识点2.对于80.X以前版本的解密拿masterkey的几种方法方法一 直接在目标机器运行Mimikatz提取方法二 转储lsass.exe 进程从内存提取masterkey方法三 导出SAM注册表 提取user hash 解密masterkey文件&#xff08;有点麻烦不太推荐&#xff09;方法四 已知用户密…

插入算法(C语言)

#include<cstdio> #include<iostream> #define N 9 using namespace std; int main() {int arr[N1] { 1,4,7,13,16,19,22,25,280 }; int in,i,j;//要插入的数字//打印要插入数字的数组所有元素printf("插入前的数组: ");for ( i 0; i <N; i){print…

STM32G030C8T6:使用外部晶振配置LED灯闪烁

本专栏记录STM32开发各个功能的详细过程&#xff0c;方便自己后续查看&#xff0c;当然也供正在入门STM32单片机的兄弟们参考&#xff1b; 本小节的目标是&#xff0c;使用STM32G030C8T6单片机&#xff0c;通过STM32CubeMX软件&#xff0c;配置并使用外部8MHz晶振&#xff0c;实…

6. Service详解

6. Service详解 文章目录 6. Service详解6.1 Service介绍6.2 Service类型6.3 Service使用6.3.1 实验环境准备6.3.2 ClusterIP类型的Service6.3.3 HeadLess类型的Service6.3.3.1 deployment和statefulset区别6.3.3.2 statefulset deployment 区别 6.3.4 NodePort类型的Service6.…

联邦蒸馏领域中,有哪些有意思的工作

联邦蒸馏领域中&#xff0c;有哪些有意思的工作 王婆卖瓜&#xff0c;自卖自夸。这个博客&#xff0c;我简要向大家推荐一下自己近期在联邦蒸馏方面的研究工作&#xff0c;按照心目中创新度从高到低进行排序&#xff0c;与工作的扎实程度以及发表的会议期刊等级无关。如有不妥…

扩展操作码指令格式

指令 操作码地址码 \quad \quad 判断几地址指令 开头4位不是全1, 则表示是三地址指令 开头4位全1, 后面4位不是全1, 则为二地址指令 前面12全1, 则为零地址指令 当然啦这只是一种扩展方法, 如果想扩展更多, 可以将1110留作扩展操作码 较短的操作码, 我们对它的译码和分析的时间…

测试:HTTP请求中,请求头(Headers)

请求头字段及其用途 在HTTP请求中&#xff0c;请求头&#xff08;Headers&#xff09;是包含了关于客户端环境和请求本身的信息的数据结构&#xff0c;它在每次请求时都会被发送到服务器。 请求头的字段非常多样&#xff0c;以下是一些常见的请求头字段及其用途的详细说明&am…