C/C++编程:curl使用

1059 篇文章 285 订阅

静默与冗长

日志模式

如果您的curl命令没有执行,或返回您所期望的内容,那么您的第一个直觉反应应该总是使用-v / --verbose选项获取更多信息.

例如,让我们看看curl在尝试一个简单的HTTP示例(将下载的数据保存到名为“saved”的文件中)

curl -v http://example.com -o saved 
* Rebuilt URL to: http://example.com/

好的,我们用一个cURL调用URL,它认为不完整,所以它帮助我们,在移动之前添加了一个尾部斜杠.

在这里插入图片描述
这告诉我们,curl现在尝试连接到这个IP地址.这意味着名称"example.com"已经解析为一个或多个地址,这是第一个(可能也是唯一的地址)curl将尝试连接到的地址.
在这里插入图片描述
它已经工作了:curl连接到了站点, 这里解释了名称如何映射到IP地址以及它连接到哪个端口.(#0)部分是cURL内部赋予这种连接的数字.如果在同一命令行中尝试多个URL,可以看到它使用更多的连接或重用连接,因此连接计数根据curl决定需要做的,可能增加或不增加.

如果我们使用 HTTPS: URL而不是HTTP: URL, 那么还将有一大堆行解释curl如何使用CA证书来验证服务器的证书,以及服务器证书中的一些细节,等等,包括选择了哪些密码和更多的TLS细节.

除了从curl内部提供的附加信息之外,-v日志模式还将使curl显示它发送和接收的所有头部.对于没有报头的协议(如FTP、SMTP、POP3等),我们可以将命令和响应视为报头,因此-v也将显示它们.

如果我们继续从上面的命令中看到的输出(但是忽略实际的HTML响应),curl将显示:

> GET / HTTP/1.1
> Host: example.com
> User-Agent: curl/7.45.0
> Accept: */*
>

这是对站点的完整HTTP请求.这个请求是默认curl 7.45.0使用中的外观,当然,在不同的版本之间可能会略有不同,特别是如果添加命令行选项,它会发生更改.

HTTP请求头的最后一行看起来是空的,事实也是这样。它表明头部和body之间的分离,在这个请求中没有"body"发送.

继续,假设一切都按照计划进行,发送的请求将从服务器获得相应的响应,该HTTP响应将以响应主体之前的一组头开始:
在这里插入图片描述
这是一组关于响应的普通HTTP报头(元数据)。第一行的“200”可能是其中最重要的一条信息,意思是“一切都很好”。

接收到的头的最后一行是空的,这是用于HTTP协议的标记,表示头的结束。

在报头之后是实际的响应体,即数据有效负载。常规的-v verbose模式不显示该数据,而只显示:

在这里插入图片描述
1270字节应该在“saved”文件中。您还可以看到,在响应中有一个名为Content-Length:的头,它包含精确的文件长度(它并不总是出现在响应中)。

静默模式

当然,冗长的反面是使curl变得更安静。使用-s(或--silent)选项,您可以让curl关闭进度计,当错误发生时不输出任何错误消息。它变得沉默。它仍然会输出您要求它输入的下载数据。

激活沉默后,您可以通过添加-S或--show-error请求它在失败时仍然输出错误消息。

跟踪选项(–trace 和 --trace-ascii)

有时候-v还不够。特别是,当你想存储包含实际传输数据的完整流时。

当curl使用https、ftps或者sftp等协议进行加密文件传输时,其他网络监控工具(比如Wireshark或者tcpdump)将无法轻松地为您完成这项工作

为此,curl提供了两个替代-v的其他选项。

–trace

--trace [filename]将以指定的文件名保存完整的跟踪信息。您还可以使用-代替文件名来将其传递给标准输出。你可以这样使用它:

curl --trace dump http://example.com

完成后,会有一个相当大的“转储”文件
在这里插入图片描述
每个发送和接收的字节都以十六进制数单独显示。

–trace-ascii

如果你认为十六进制没有帮助,你可以尝试——trace-ascii [filename]代替,也接受’-'作为标准输出:

curl --trace-ascii  dump http://example.com

在这里插入图片描述

–trace-time

该选项为所有详细/跟踪输出添加一个高分辨率的计时器,用于打印该行。它可以使用常规的-v / --verbose选项以及--trace--trace-ascii

一个例子看起来像这样:

curl -v --trace-time http://example.com

在这里插入图片描述
这些线路都是当地时间,如小时:分钟:秒,然后是那一秒的微秒数。

Write out

--write-out简称-w,在传输完成后写出信息,它有大量的变量可以包含在输出中,这些变量已经设置了来自传输的值或者信息

你告诉curl写一个字符串,只需要将字符串传递给这个选项:

curl -w "formatted string" http://example.com/  #默认

你也可以让curl从给定的文件中读取该字符串,如果你在字符串前面加上’@’:

curl -w @filename http://example.com/

或者甚至让curl从stdin读取字符串,如果你使用’-'作为文件名:

curl -w @- http://example.com/

可以通过在字符串中写入%{variable_name}来访问可用的变量,然后该变量将被正确的值替换。要输出一个普通的’%’,只需将它写入%%即可。你也可以通过使用’\n’, ‘\r’回车和’\t’制表空间来输出换行符。

(%-符号在Windows命令行中是特殊的,在使用该选项时,所有出现的%都必须翻倍。)

例如,我们可以从HTTP传输中输出内容类型和响应代码,用换行符和一些额外的文本分隔,如下所示:

curl -w "Type: %{content_type}\nCode: %{response_code}\n" http://example.com

该特性将输出写入stdout,因此您可能希望确保不会将下载的内容也发送到stdout,因为这样可能很难分离出数据。

版本

要了解已经安装的curl的版本,请运行

curl --version
curl -V

在这里插入图片描述

  • 工具的主版本号(为该工具构建的“平台”和libcurl版本)其余部分包含这个curl版本所使用的第三方组件的名称
  • 发布这个curl版本的日期
  • 所支持的按字母顺序排列的所有传输协议
  • 支持的功能列表
    • alt svc:支持alt svc:header
    • AsynchDNS:此旋度使用异步名称解析。异步名称解析可以使用c-ares或线程解析程序后端来完成。

持久连接

当设置到站点的TCP连接时,curl会将旧连接保留一段时间,这样如果下一次传输到同一个主机,它就可以再次重用同一个连接,从而节省大量的时间。我们称之为“持久链接”。curl总是试图保持连接的活动性,并尽可能的重用现有的连接

但是,curl命令行工具使连接在运行期间保持活动状态,因此一旦它返回到您的命令行,它就必须关闭所有当前打开的连接(同时释放并清理它使用的所有其他缓存,以减少后续操作的时间)。我们将活动连接池称为“连接缓存”。

如果您想对同一个主机或同一个基本URL执行N个传输或操作,那么您可以尝试在尽可能少的curl命令行中执行这些操。

下载

将数据从服务器下载到运行curl的机器上。

下载到底是什么

通过给curl一个url来指定要下载的资源。除非另有说明,否则curl默认为下载url,URL标识要下载的内容。在本例中,要下载的URL为“http://example.com":

curl http://example.com

默认curl会将下载的数据输出到stdout

如果在命令行中指定多个URL,curl将逐个下载每个URL。在第一次传输完成之前,它不会开始第二次传输,等等。

下载保存

-o [filename]将下载保存在中filename,其中filename只是一个文件名、一个文件名的相对路径或一个文件的完整路径。

另外请注意,您可以将-o放在URL之前或之后;这没有什么区别:

curl -o output.html http://example.com/
curl -o /tmp/index.html http://example.com/
curl http://example.com -o ../../folder/savethis.html
curl -o file.txt ftp://example.com/path/to/file-name.ext

也可以通过-O选项通过选取您提供的URL的文件名部分来选择要使用的本地文件名。

curl -O http://example.com/file.html

现有一需求去curl 在香港的一个接口, 返回值有时正常有时报错 connection reset by peer .

思路: 若 执行成功 $?返回 0 , 不成功则返回其他数字

#!/bin/bash
 
curl http://47.9********:31234/ins/search/topsearch/data/ &> /dev/null
 
if [ $? -eq 0 ]; then
    
    curl_ins_search=1
 
else
    curl_ins_search=0
 
fi
 
echo $curl_ins_search 

显示下载进度条

 curl -# -O http://www.linux.com/dodo1.JPG

在这里插入图片描述

不会显示下载进度信息


参见

从服务器获取目标文件名

HTTP服务器可以选择在响应中提供名为Content-Disposition:的头,该头文件可能包含所传递内容的建议名字名,可以告诉curl使用该提示来命名其本地文件。-J / --remote-header-name启用此功能。注意:

  • 它将只使用建议文件名的最右边部分,因此服务器建议的任何路径或目录都将被剥离。

  • 由于文件名完全由服务器选择,因此如果服务器碰巧提供这样的文件名,curl当然会覆盖当前目录中任何先前存在的本地文件。

  • 文件名编码和字符集问题。curl不会以任何方式对名称进行解码,因此您可能会得到一个URL编码的文件名,而浏览器会使用一个合理的字符集将其解码为更可读的文件名。

压缩

curl允许您请求HTTP和HTTPS服务器提供数据的压缩版本,然后在数据到达时对其执行自动解压缩。

HTTP压缩可以使用两种不同的机制来完成,一种被认为是“正确的方式”,另一种则是每个人实际使用的方式,是广泛流行的方式。压缩HTTP内容的常用方法是使用content-Encoding头。您要求curl将其与–compressed选项一起使用:

curl --compressed http://example.com/

启用此选项后(如果服务器支持),它将以压缩方式传递数据,curl将在保存数据或将其发送到stdout之前对其进行解压缩。这通常意味着,作为一个用户,除了可能注意到更快的传输之外,您不会真正看到或体验到压缩。

–compressed选项要求使用支持的压缩算法之一进行内容编码压缩。还有一种罕见的传输编码方法,它是为这种自动方法创建的头文件,但从未被广泛采用。您可以告诉curl使用–tr编码请求传输编码压缩:

curl --tr-encoding http://example.com/

shell重定向

当你从shell或者其他命令行提示系统调用curl时,该环境通常为你提供一组输出重定向功能,可以将stdout指向一个>文件名的文件。当然,使用-o或-o是多余的。

curl http://example.com/ > example.html

将输出重定向到一个文件会将curl的所有输出重定向到该文件,因此即使您请求将多个URL传输到stdout,重定向输出也会将所有URL的输出存储在该文件中。

curl http://example.com/1 http://example.com/2 > files

unixshell通常允许您分别重定向stderr流。stderr流通常是一个也显示在终端中的流,但是您可以将它与stdout流分开重定向。stdout流用于数据,而stderr是元数据和错误等,它们不是数据。您可以使用2>文件重定向stderr,如下所示:

curl http://example.com > files.html 2>errors

多次下载

由于curl可以被告知在一个命令行中下载许多url,当然,有时您需要将这些下载存储在命名良好的本地文件中。

理解这一点的关键是,每个下载URL都需要自己的“存储指令”。如果没有所说的“存储指令”,curl将默认向stdout发送数据。如果您请求两个URL,并且只告诉curl在哪里保存第一个URL,那么第二个URL将被发送到stdout。这样地:

curl -o one.html http://example.com/1 http://example.com/2

“存储指令”的读取和处理顺序与下载URL相同,因此它们不必以任何方式位于URL旁边。您可以先将所有输出选项归集到一起,最后归集到一起,或者与url交错归集。你自己选择。

这些示例的工作方式都相同:

curl -o 1.txt -o 2.txt http://example.com/1 http://example.com/2
curl http://example.com/1 http://example.com/2 -o 1.txt -o 2.txt
curl -o 1.txt http://example.com/1 http://example.com/2 -o 2.txt
curl -o 1.txt http://example.com/1 -o 2.txt http://example.com/2

类似地,-O只是单个下载的指令,因此如果您下载多个URL,请使用更多URL:

curl -O -O http://example.com/1 http://example.com/2

速率限制

当curl传输数据时,它将尝试以尽可能快的速度传输数据。它适用于上传和下载。

然而,有时您会发现,让curl在本地网络连接上耗尽其他网络功能是不方便的。在这些情况下,您可能需要告诉curl放慢速度,以便其他网络用户也有更好的机会获得他们的数据。使用--limitrate[speed]可以告诉curl不要超过给定的每秒字节数。速率限制值可以用字母后缀给出,K、M和G中的一个表示千字节、兆字节和千兆字节。

要使curl下载数据的速度不超过每秒200 KB,请执行以下操作:

curl https://example.com/ --limit-rate 200K

最大文件大小

当您想确保curl命令行不会尝试下载过大的文件时,如果curl在传输开始前知道文件大小,您可以在下载之前指示它停止

curl --max-filesize 100000 https://example.com/

给curl一个你能接受的最大的下载量(字节数),如果curl能在传输开始前计算出大小,它将在尝试下载更大的东西之前中止。

在许多情况下,curl无法计算传输开始时的大小,并且此选项不会影响这些传输,即使它们最终可能大于指定的量。

Metalink

Metalink是一种文件描述标准,它告诉客户端相同内容所在的多个位置。然后,客户机可以选择从一个或多个源传输该内容。

当被要求使用–Metalink选项时,curl支持Metalink格式。然后给定的URL应该指向Metalink文件。例如:

curl --metalink https://example.com/example.metalink

如果出现错误(例如文件或服务器不可用),curl将使用文件中列出的镜像进行故障转移。它还将在下载完成后验证文件的哈希值。Metalink文件本身在内存中下载和处理,而不是存储在本地文件系统中。

raw

当使用--raw时,它将禁用所有内容或传输编码的内部HTTP解码,而是将curl传递给未更改的原始数据。

如果您正在编写一个中间软件,并且希望将内容传递给另一个HTTP客户机,并允许该客户机执行解码,则通常会使用这种方法。

恢复下载

恢复下载意味着首先检查本地已经存在的内容的大小,然后要求服务器发送其余内容,以便可以附加。curl还允许在一个自定义点上恢复传输,而实际上没有任何本地存在的东西。

curl支持多种协议的恢复下载。用-C、-continue-at选项告诉它从何处开始传输,该选项可以是一个普通的数字字节计数器偏移量,也可以是一个字符串,该字符串要求curl根据它所知道的内容自己计算出来。使用-,curl将使用目标文件名来计算本地已经存在的数据量,并在从服务器请求更多数据时将其用作偏移量。

从字节偏移量100开始下载FTP文件:

curl --continue-at 100 ftp://example.com/bigfile

继续下载先前中断的下载:

curl --continue-at - http://example.com/bigfile -O

如果您只想从传输的远程资源中获得一个特定的字节范围,您可以只要求这个范围。例如,当您只需要偏移量100的1000个字节以避免下载整个巨大的远程文件时:

curl --range 100-1099 http://example.com/bigfile

上传

上传是向远程服务器发送数据的术语。每个协议的上传方式都不同,有几个协议甚至允许以不同的方式上传数据。

允许上传的协议

您可以使用以下协议之一上载数据:FILE、FTP、FTPS、HTTP、HTTPS、IMAP、IMAPS、SCP、SFTP、SMB、SMBS、SMTP、SMTPS和TFTP。

HTTP提供了几种“上传”

HTTP(及其更大的兄弟HTTPS)提供了几种不同的方式将数据上传到服务器,curl提供了简单的命令行选项,下面介绍了三种最常见的方式。

HTTP的一个有趣的细节是,上传也可以是下载,在相同的操作中,事实上许多下载都是通过HTTP POST启动的。

POST

POST是一种HTTP方法,它被发明用来向接收数据的web应用程序发送数据,例如,它是web上最常见的HTML表单的工作方式。它通常向接收器发送相对少量的数据块。

上载类型通常使用-d或–data选项完成,但是还有一些额外的更改。

阅读HTTP POST with curl一章中关于如何使用curl的详细描述。

multipart formpost

multipart formpost用于网站上的HTML表单中;通常在涉及文件上载时使用。这种类型的上传也是一种HTTP POST,但它发送的数据格式符合一些特殊规则,这就是“multipart”名称的含义。

由于它发送的数据格式完全不同,您不能随心所欲地选择使用哪种类型的POST,但这完全取决于接收服务器端的期望和处理能力。

HTTP multipart formposts是用-F完成的。请参阅HTTP multipart formposts一章中的详细描述。

PUT

PUT是一种上传方法,它被设计用来发送一个完整的资源,以便原样放到远程站点上,甚至替换那里的现有资源。这也是目前在web上使用最少的HTTP上传方法,而且很多(如果不是大多数的话)web服务器甚至没有启用PUT。

您可以使用-T选项和要上载的文件发送HTTP上载:

curl -T uploadthis http://example.com/

ftp上传

使用FTP,您可以看到将要访问的远程文件系统。您可以准确地告诉服务器要将上载放置在哪个目录中以及要使用哪个文件名。如果用斜杠指定上载URL,curl会将本地使用的文件名附加到URL,然后这将是远程存储时使用的文件名:

curl -T uploadthis ftp://example.com/this/directory/

因此,如果您希望在远程端选择不同于本地使用的文件名,请在URL中指定:

curl -T uploadthis ftp://example.com/this/directory/remotename

更多请参考

SMTP上传

将邮件正文上传到SMTP服务器。使用SMTP时,还需要在邮件正文中包含所需的所有电子邮件头(收件人:、发件人:、日期:,等等),因为curl根本不会添加任何邮件头。

curl -T mail smtp://mail.example.com/ --mail-from user@example.com

更多请参考

ftp总结

(1) 查看文件

# 查看 FTP 指定目录(目录必须以"/"结尾)下的文件列表 
curl ftp://192.168.0.100/aaDir/ -u "user:passwd"

# 查看 FTP 指定文件的内容(直接输出到终端) 
curl ftp://192.168.0.100/aaDir/aa.txt -u "user:passwd"

# 用户名 和 密码 的另一种写法(查看 FTP 服务器指定目录)
curl ftp://user:passwd@192.168.0.200/aaDir/

(2) 上传文件

# 上传 aa.txt 文件到 FTP 指定目录下(目录必须以"/"结尾), 并以 原文件名 命名保存
curl ftp://192.168.0.100/aaDir/ -u "user:passwd" -T "aa.txt"

# 上传 aa.txt 文件到 FTP 指定目录下, 并以 bb.txt 命名保存
curl ftp://192.168.0.100/aaDir/bb.txt -u "user:passwd" -T "aa.txt"

# 同时上传多个文件
curl ftp://192.168.0.100/aaDir/ -u "user:passwd" -T "{aa.txt,bb.txt}"

(3)下载文件

# 下载 FTP 指定文件 /aaDir/aa.txt, 以原文件名命名保存到当前目录 
curl ftp://192.168.0.100/aaDir/aa.txt -u "user:passwd" -O

# 下载 FTP 指定文件 /aaDir/aa.txt, 以 bb.txt 命名保存
curl ftp://192.168.0.100/aaDir/aa.txt -u "user:passwd" -o bb.txt

(4) 执行 FTP 协议命令

curl 执行 FTP 命令格式:

单条命令: curl [-options] -X “FTP命令”
多条命令: curl [-options] -Q “FTP命令” -Q “FTP命令”

# 
# 创建文件夹,/aaDir/ 目录(目录必须以"/"结尾)下创建 bbDir 文件夹
#
curl -u "user:passwd" ftp://192.168.0.100/aaDir/ -X "MKD bbDir"

# 
# 删除文件夹, 删除 /aaDir/ 目录下的 bbDir 文件夹(文件夹必须为空)
#
curl -u "user:passwd" ftp://192.168.0.100/aaDir/ -X "RMD bbDir"

# 
# 删除文件, 删除 /aaDir/ 目录下的 aa.txt 文件
#
curl -u "user:passwd" ftp://192.168.0.100/aaDir/ -X "DELE aa.txt"

#
# 重命名, 重命名需要连续执行两条命令, 使用两个 -Q 参数连续执行两条命令(必须先 RNFR, 后 RNTO)
#
curl -u "user:passwd" ftp://192.168.0.100/ -Q "RNFR OldPath" -Q "RNTO NewPath"

其他 FTP 协议命令参考:

http://www.nsftools.com/tips/RawFTP.htm
https://en.wikipedia.org/wiki/List_of_FTP_commands

参考

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值