第一部分:RTSP协议

一、 RTSP协议概述

RTSP(Real-Time Stream Protocol )是一种基于文本的应用层协议,在语法及一些消息参数等方面,RTSP协议与HTTP协议类似。

RTSP被用于建立的控制媒体流的传输,它为多媒体服务扮演“网络远程控制”的角色。尽管有时可以把RTSP控制信息和媒体数据流交织在一起传送,但一般情况RTSP本身并不用于转送媒体流数据。媒体数据的传送可通过RTP/RTCP等协议来完成。

一次基本的RTSP操作过程是:

  1> 客户端连接到流服务器并发送一个RTSP描述命令(DESCRIBE)。

  2> 流服务器通过一个SDP描述来进行反馈,反馈信息包括流数量、媒体类型等信息。

  3> 客户端再分析该SDP描述,并为会话中的每一个流发送一个RTSP建立命令(SETUP),RTSP建立命令告诉服务器客户端用于接收媒体数据的端口。

  4> 流媒体连接建立完成后,客户端发送一个播放命令(PLAY),服务器就开始在UDP上传送媒体流(RTP包)到客户端。

  5> 在播放过程中客户端还可以向服务器发送命令来控制快进、快退和暂停等。

  6> 最后,客户端可发送一个终止命令(TERADOWN)来结束流媒体会话

二、 RTSP协议与HTTP协议区别

RTSP引入了几种新的方法,比如DESCRIBE、PLAY、SETUP 等,并且有不同的协议标识符,RTSP为rtsp 1.0,HTTP为http 1.1;

HTTP是无状态的协议,而RTSP为每个会话保持状态;

RTSP协议的客户端和服务器端都可以发送Request请求,而在HTTPF 协议中,只有客户端能发送Request请求。

在RTSP协议中,载荷数据一般是通过带外方式来传送的(除了交织的情况),及通过RTP协议在不同的通道中来传送载荷数据。而HTTP协议的载荷数据都是通过带内方式传送的,比如请求的网页数据是在回应的消息体中携带的。

使用ISO 10646(UTF-8) 而不是ISO 8859-1,以配合当前HTML的国际化;

RTSP使用URI请求时包含绝对URI。而由于历史原因造成的向后兼容性问题,HTTP/1.1只在请求中包含绝对路径,把主机名放入单独的标题域中;

三、 RTSP重要术语

集合控制(Aggregate control ):

对多个流的同时控制。对音频/视频来讲,客户端仅需发送一条播放或者暂停消息就可同时控制音频流和视频流。

实体(Entity):

作为请求或者回应的有效负荷传输的信息。由以实体标题域(entity-header field)形式存在的元信息和以实体主体(entity body)形式存在的内容组成

容器文件(Container file):

可以容纳多个媒体流的文件。RTSP服务器可以为这些容器文件提供集合控制。

RTSP会话(RTSP session ):

RTSP交互的全过程。对一个电影的观看过程,会话(session)包括由客户端建立媒体流传输机制(SETUP),使用播放(PLAY)或录制(RECORD)开始传送流,用停止(TEARDOWN)关闭流。

四、 RTSP请求消息

消息格式:

方法 URI RTSP版本       CR LF

消息头 CR LF          CR LF

消息体 CR LF

其中方法包括OPIONS、DESCRIBE、SETUP、PLAY、TEARDOWN等,URI是接受方的地址,例如:rtsp://192.168.0.1/video1.3gp。

RTSP版本一般都是 RTSP/1.0。每行后面的CR LF表示回车换行,需要接受端有相应的解析,最后一个消息头需要有两个CR LF

消息体是可选的,有的Request消息并不带消息体。

五、 RTSP回应消息

消息格式:

RTSP版本 状态码 解释      CR LF

消息头 CR LF          CR LF

消息体 CR LF

其中RTSP版本一般都是RTSP/1.0,状态码是一个数值,用于表示Request消息的执行结果,比如200表示成功,解释是与状态码对应的文本解释.

六、 RTSP 重要方法

OPTIONS:

用于得到服务器提供的可用方法;

如:

OPTIONS rtsp://192.168.20.136:5000/xxx666 RTSP/1.0

CSeq: 1

服务器的回应信息会在Public字段列出提供的方法。如:

RTSP/1.0 200 OK

CSeq: 1         //每个回应消息的cseq数值和请求消息的cseq相对应

Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE

DESCRIBE:

客户端向服务器端发送DESCRIBE,用于得到URI所指定的媒体描述信息,一般是SDP信息。客户端通过Accept头指定客户端可以接受的媒体述信息类型。

如:

C->S: DESCRIBE rtsp://server.example.com/fizzle/foo RTSP/1.0

CSeq: 312

Accept: application/sdp, application/rtsl, application/mheg)

服务器回应URI指定媒体的描述信息:

如:

S->C: RTSP/1.0 200 OK

CSeq: 312

Date: 23 Jan 1997 15:35:06 GMT

Content-Type: application/sdp  //表示回应为SDP信息

Content-Length: 376

//这里为一个空行

//以下为具体的SDP信息

v=0

o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4

s=SDP Seminar

i=A Seminar on the session description protocol

u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps

e=mjh@isi.edu (Mark Handley)

c=IN IP4 224.2.17.12/127

t=2873397496 2873404696

a=recvonly

m=audio 3456 RTP/AVP 0

m=video 2232 RTP/AVP 31

m=whiteboard 32416 UDP WB

a=orient:portrait

媒体初始化是任何基于RTSP系统的必要条件,但RTSP规范并没有规定它必须通过DESCRIBE方法完成。RTSP客户端可以通过以下方法来接收媒体描述信息:

a) 通过DESCRIBE方法;

b) 其它一些协议(HTTP,email附件,等);

c) 通过命令行或标准输入设备

SETUP:

用于确定转输机制,建立RTSP会话。客户端能够发出一个SETUP请求为正在播放的媒体流改变传输参数,服务器可能同意这些参数的改变。若是不同意,它必须响应错误"455 Method Not Valid In This State"。

Request 中的Transport头字段指定了客户端可接受的数据传输参数;Response中的Transport 头字段包含了由服务器选出的传输参数。

如:

C->S: SETUP rtsp://example.com/foo/bar/baz.rm RTSP/1.0

CSeq: 302

Transport: RTP/AVP;unicast;client_port=4588-4589

服务器端对SETUP Request产生一个Session Identifiers。

如:

S->C: RTSP/1.0 200 OK

CSeq: 302

Date: 23 Jan 1997 15:35:06 GMT

Session: 47112344  //产生一个Session ID

Transport: RTP/AVP;unicast;

client_port=4588-4589;server_port=6256-6257

PLAY:

PLAY方法告知服务器通过SETUP中指定的机制开始发送数据 。在尚未收到SETUP请求的成功应答之前,客户端不可以发出PLAY请求。

PLAY请求将正常播放时间(normal play time)定位到指定范围的起始处,并且传输数据流直到播放范围结束。PLAY请求可能被管道化(pipelined),即放入队列中(queued);服务器必须将PLAY请求放到队列中有序执行。也就是说,后一个PLAY请求需要等待前一个PLAY请求完成才能得到执行。

比如,在下例中,不管到达的两个PLAY请求之间有多紧凑,服务器首先play第10到15秒,然后立即第20到25秒,最后是第30秒直到结束。

C->S: PLAY rtsp://audio.example.com/audio RTSP/1.0

CSeq: 835

Session: 12345678

Range: npt=10-15

C->S: PLAY rtsp://audio.example.com/audio RTSP/1.0

CSeq: 836

Session: 12345678

Range: npt=20-25

C->S: PLAY rtsp://audio.example.com/audio RTSP/1.0

CSeq: 837

Session: 12345678

Range: npt=30-

Range头可能包含一个时间参数。该参数以UTC格式指定了播放开始的时间。如果在这个指定时间后收到消息,那么播放立即开始。时间参数可能用来帮助同步从不同数据源获取的数据流。

不含Range头的PLAY请求也是合法的。它从媒体流开头开始播放,直到媒体流被暂停。如果媒体流通过PAUSE暂停,媒体流传输将在暂停点(the pause point)重新开始。

如果媒体流正在播放,那么这样一个PLAY请求将不起更多的作用,只是客户端可以用此来测试服务器是否存活。

PAUSE:

PAUSE请求引起媒体流传输的暂时中断。如果请求URL中指定了具体的媒体流,那么只有该媒体流的播放和记录被暂停(halt)。比如,指定暂停音频,播放将会无声。如果请求URL指定了一组流,那么在该组中的所有流的传输将被暂停。如:

C->S: PAUSE rtsp://example.com/fizzle/foo RTSP/1.0

CSeq: 834

Session: 12345678

S->C: RTSP/1.0 200 OK

CSeq: 834

Date: 23 Jan 1997 15:35:06 GMT

PAUSE请求中可能包含一个Range头用来指定何时媒体流暂停,我们称这个时刻为暂停点(pause point)。该头必须包含一个精确的值,而不是一个时间范围。媒体流的正常播放时间设置成暂停点。当服务器遇到在任何当前挂起(pending)的PLAY请求中指定的时间点后,暂停请求生效。如果Range头指定了一个时间超出了任何一个当前挂起的PLAY请求,将返回错误"457 Invalid Range" 。如果一个媒体单元(比如一个音频或视频禎)正好在一个暂停点开始,那么表示将不会被播放或记录。如果Range头缺失,那么在收到暂停消息后媒体流传输立即中断,并且暂停点设置成当前正常播放时间。

TEARDOWN:

TEARDOWN请求终止了给定URI的媒体流传输,并释放了与该媒体流相关的资源。如:

C->S: TEARDOWN rtsp://example.com/fizzle/foo RTSP/1.0

CSeq: 892

Session: 12345678

S->C: RTSP/1.0 200 OK

CSeq: 892

七、 RTSP重要头字段参数

Accept:

用于指定客户端可以接受的媒体描述信息类型。比如:

Accept: application/rtsl, application/sdp;level=2

Bandwidth:

用于描述客户端可用的带宽值。

CSeq:

指定了RTSP请求回应对的序列号,在每个请求或回应中都必须包括这个头字段。对每个包含一个给定序列号的请求消息,都会有一个相同序列号的回应消息。

Rang:

用于指定一个时间范围,可以使用SMPTE、NTP或clock时间单元。

Session:

Session头字段标识了一个RTSP会话。Session ID 是由服务器在SETUP的回应中选择的,客户端一当得到Session ID后,在以后的对Session 的操作请求消息中都要包含Session ID.

Transport:

Transport头字段包含客户端可以接受的转输选项列表,包括传输协议,地址端口,TTL等。服务器端也通过这个头字段返回实际选择的具体选项。如:

Transport: RTP/AVP;multicast;ttl=127;mode="PLAY",

RTP/AVP;unicast;client_port=3456-3457;mode="PLAY"

八、 简单的RTSP消息交互过程

C表示RTSP客户端,S表示RTSP服务端

第一步:查询服务器端可用方法

  C->S:OPTION request       //询问S有哪些方法可用

  S->C:OPTION response    //S回应信息的public头字段中包括提供的所有可用方法

第二步:得到媒体描述信息

  C->S:DESCRIBE request      //要求得到S提供的媒体描述信息

  S->C:DESCRIBE response    //S回应媒体描述信息,一般是sdp信息

第三步:建立RTSP会话

  C->S:SETUP request             //通过Transport头字段列出可接受的传输选项,请求S建立会话

  S->C:SETUP response          //S建立会话,通过Transport头字段返回选择的具体转输选项,并返回建立的Session ID;

第四步:请求开始传送数据

  C->S:PLAY request        //C请求S开始发送数据

  S->C:PLAY response            //S回应该请求的信息

第五步: 数据传送播放中

  S->C:发送流媒体数据    // 通过RTP协议传送数据

第六步:关闭会话,退出

  C->S:TEARDOWN request      //C请求关闭会话

  S->C:TEARDOWN response //S回应该请求

上述的过程只是标准的、友好的rtsp流程,但实际的需求中并不一定按此过程。

其中第三和第四步是必需的!第一步,只要服务器客户端约定好,有哪些方法可用,则option请求可以不要。第二步,如果我们有其他途径得到媒体初始化描述信息(比如http请求等等),则我们也不需要通过rtsp中的describe请求来完成。

第二部分:SDP协议

一、 SDP协议概述

SDP(Session Description Protocol )会话描述协议,用于描述多媒体会话,它为会话通知、会话初始和其它形式的多媒体会话初始等操作提供服务。

SDP 的设计宗旨是通用性协议,所有它可以应用于很大范围的网络环境和应用程序,但 SDP 不支持会话内容或媒体编码的协商操作。

SDP信息包括:

  • 会话名称和目标;
  • 会话活动时间;
  • 构成会话的媒体;
  • 有关接收媒体的信息、地址等。

二、 SDP格式

SDP 信息是文本信息,UTF-8 编码采用 ISO 10646 字符设置。

SDP 会话描述如下(标注*符号的表示可选字段):

  • v= (协议版本)
  • o= (所有者/创建者和会话标识符)
  • s= (会话名称)
  • i=* (会话信息)
  • u=* (URI 描述)
  • e=* (Email 地址)
  • p=* (电话号码)
  • c=* (连接信息 ― 如果包含在所有媒体中,则不需要该字段)
  • b=* (带宽信息)

  一个或更多时间描述(如下所示):

  • z=* (时间区域调整)
  • k=* (加密密钥)
  • a=* (0个或多个会话属性线路)
  • 0个或多个媒体描述(如下所示)

  时间描述

  • t= (会话活动时间)
  • r=* (0或多次重复次数)

  媒体描述

  • m= (媒体名称和传输地址)
  • i=* (媒体标题)
  • c=* (连接信息 — 如果包含在会话层则该字段可选)
  • b=* (带宽信息)
  • k=* (加密密钥)
  • a=* (0个或多个会话属性线路)

三、 SDP示例

v=0

o=mhandley 2890844526 2890842807 IN IP4 126.16.64.4

s=SDP Seminar

i=A Seminar on the session description protocol

u=http://www.cs.ucl.ac.uk/staff/M.Handley/sdp.03.ps

e=mjh@isi.edu (Mark Handley)

c=IN IP4 224.2.17.12/127

t=2873397496 2873404696

a=recvonly

m=audio 49170 RTP/AVP 0

m=video 51372 RTP/AVP 31

m=application 32416 udp wb

a=orient:portrait

//字段解释

V=0     ;Version 给定了SDP协议的版本

o=<username> <session id> <version> <network type> <address type>

<address>; Origin ,给定了会话的发起者信息

s=<session name> ;给定了Session Name

i=<session description> ; Information 关于Session的一些信息

u=<URI> ; URI

e=<email address>    ;Email

c=<network type> <address type> <connection address> ;Connect Data包含连接数据

t=<start time> <stop time> ;Time

a=<attribute>     ; Attribute

a=<attribute>:<value>

m=<media> <port> <transport> <fmt list> ; Media Announcements

第三部分:MMS协议

一、 MMS协议概述

传输音、视频的通用服务器有两种,都有各自的优缺点。分别是:标准WEB服务器和流媒体服务器。标准WEB服务器使用HTTP协议。流媒体服务器使用两种协议提供媒体服务。这两种协议分别是HTTP1.0或1.1以及MMS(Multi Media Server)协议。流媒体服务器使用的HTTP协议是经过修改的版本,扩展了语法命令以支持实时传输。这是普通HTTP所不支持的。

使用两种协议提供媒体服务和WEB服务器有着显著区别。一个区别是在WEB服务器上使用标准HTTP协议的数据不需要一个特殊的服务器和软件进行浏览甚至下载。另外一个区别是使用MMS(例如Microsoft Windows Media Services)的流媒体服务器通过流形式提供媒体给使用者。流媒体服务器可以处理大量数据。

MMS是(Multimedia Messaging Service)的缩写,中文意为多媒体短信服务,它最大的特色就是支持多媒体功能。多媒体信息使具有功能全面的内容和信息得以传递,这些信息包括图像、音频信息、视频信息、数据以及文本等多媒体信息,可以支持语音、因特网浏览、电子邮件、会议电视等多种高速数据业务,在GPRS网络的支持下,以WAP无线应用协议为载体传送视频片段、图片、声音和文字。多媒体信息业务可实现即时的手机端到端、手机终端到互联网或互联网到手机终端的多媒体信息传送。

MMS信息是以标准方式压缩的,因此,接收一方可以确认它不支持的内容格式,并以控制方式进行处置。这也是互联网上解决内容交互问题所用的方法。

MMS标准推荐支持的媒体类型有:JPEG、GIF、TEXT、AMR语音和其他一些非主流格式。为了获得更好的交互性,诺基亚和其他一些制造商已共同拟就了“MMS一致性文件”,列出了MMS手机能支持的最小一组内容类型。

MMS是微软的私有流媒体协议。它的最初目的是通过网络传输多媒体广播、视频、音轨、现场直播和一系列的实时或实况材料。使用这个协议的观众可以通过电脑观看电视图像或音轨。微软为有网络连接的家用电脑使用者开发了免费软件。MMS建立在UDP或TCP传输/网络层上,是属于应用层的。

使用TCP的MMS上URL是MMS://或者MMST://,如果是UDP的MMS使用MMSU://。在低带宽的情况下推荐使用UDP连接。HTTP带有大量的头信息,UDP一般不能通过防火墙,在有防火墙的情况下使用HTTP。TCP的无差错特性是非常诱人的,它的吞吐量比UDP小,但是在下载MMS的时候TCP是不二的选择。

MMS协议是以包和数据块的形式从服务器向使用者发送数据到你的计算机上。服务器上的媒体文件是以ASF或WMA形式存在。直播通过流媒体服务器组装成数据包。如果是TV/视频的话,一个包可能会由多个流组成,但是语音广播就只有一个流。可以认为多个流是被混合到了一个实际的包中。包中发送的流取决于媒体类型。下面会涉及到更多关于流的内容。

二、MMS协议包

MMS协议包有两种:命令包和数据包。

MMS协议使用一段命令来完成多种人物,比如:连接到流服务器、请求文件、丢包重传请求及类似事宜。这是应用层协议,在这一层上媒体使用者和服务器进行通讯。这些都要传输到使用者。

MMS命令包头
下面分析MMS包头结构。以下是小端格式。左边=LSB,右边=MSB。0f 00 00 00 就相当于0f。

开始---->

4bytes = 01 00 00 [00]

从client发出的格式是固定的。[00]域从服务器发出的时候是可以发生变化的。现在不能理解这个比特的含义--总是0,可能是版本号。

4bytes = CE FA 0B B0

命令ID值,或许是版本或者序列号。这总是固定的。如果你按照大端来读就是“Boob Face”.可能是巧合吧。

4bytes

命令数据包长度,计算到全部数据末尾。单位为比特,从协议类型域之后开始计算。

4bytes = 4D 4D 53 20

协议类型,固定值为MMS<空格>的ASCII。

4 bytes

直到包尾的长度,8比特为单位。包含自身数据域。例如,8bytes,value = 1。

4 bytes

序列号。命令是由客户端发向服务器的,序列号的计数从0开始。命令的响应拥有同样的序列号。也就是说序列号就是ECHO。客户端总是发起命令。

8 bytes

双精度时间戳,用于网络时序。

4 bytes

到包尾的长度,单位为8比特。包括自身。例如,8 bytes ,value = 1。

Comm 2bytes | Dir 2bytes

标志命令方向流的值。命令值含义参考MMS命令列表。对于方向域,0x03 = 向服务器,0x02 = 向客户端。

----> 长度为40比特的命令头到此为止。

命令包长度跟在其后,先是‘prefix 1’然后是‘prefix 2’,接下来直到命令包结束都是‘command specific data’。

命令指定数据可以是字符串文本‘Unicode 16bit’,或者是raw 8位数据。

在prefix 数据解说之后可以看到命令特定数据段含义。

命令包通常都包括上述内容,最小字节是40。

命令包头是作为命令发送的最小包。

注意:包长域包括到包末尾所有的padding。

【转】RTSP协议学习笔记的更多相关文章

  1. RTSP协议学习笔记

    一.        RTSP协议概述 RTSP(Real-Time Stream Protocol )是一种基于文本的应用层协议,在语法及一些消息参数等方面,RTSP协议与HTTP协议类似. RTSP ...

  2. HTTP协议学习笔记(四)

    HTTP协议学习笔记(四) 与 HTTP 协作的 Web 服务器 一台 Web 服务器可搭建多个独立域名的 Web 网站,也可作为通信路径上的中转服务器提升传输效率. 1.用单台虚拟主机实现多个域名 ...

  3. HTTP协议学习笔记(三)

    HTTP协议学习笔记(三) 1.状态码告知从服务器端返回的请求结果 状态码的职责是当客户端向服务端向服务端发送请求时,描述返回的请求结果.借助状态码,用户可以知道服务端是正常处理了请求,还是出现了错误 ...

  4. HTTP协议学习笔记(二)

    HTTP协议学习笔记(二) 1.HTTP报文 HTTP报文:用于HTTP协议交互的信息.请求报文:请求端(客户端)的HTTP报文叫做请求报文.响应报文:响应端(服务端)的HTTP报文叫做响应报文. H ...

  5. HTTP协议学习笔记(一)

    HTTP协议学习笔记(一) 1.HTTP协议用于客户端和服务端之间的通信 客户端:请求访问文本或图像等资源的一端服务端:提供资源响应的一端 在两台计算机之间使用HTTP协议通信时,在一条通信线路上必定 ...

  6. TCP/IP协议学习笔记

    计算机网络基础知识复习汇总:计算机网络基础知识复习 HTTP协议的解析:剖析 HTTP 协议 一个系列的解析文章: TCP/IP详解学习笔记(1)-- 概述 TCP/IP详解学习笔记(2)-- 数据链 ...

  7. RSA算法、SSL协议学习笔记

    最近学习计算机网络,涉及到SSL协议,我想起了去年密码学课程讲过的非对称加密RSA算法,结合阮老师的博客,写写学习笔记,这里再回忆一下. RSA算法 RSA算法是一种非对称密码算法,所谓非对称,就是指 ...

  8. 网络协议学习笔记(二)物理层到MAC层,交换机和VLAN,ICMP与ping原理

    概述 之前网络学习笔记主要讲解了IP的诞生,或者说整个操作系统的诞生,一旦有了IP,就可以在网络的环境里和其他的机器展开沟通了.现在开始给大家讲解关于网络底层的相关知识. 从物理层到MAC层:如何在宿 ...

  9. tcp/ip协议学习笔记一

    一. 简述 以前在学校学习计算机网络的时候学习多是网络7层模型OSI,了解了一些基本的计算机网络概念和协议通信格式,但是一直没弄明白其中的原理,包括各层之间的关系,应用,还有一些常见的令牌环网到底是什 ...

随机推荐

  1. 【转】打包AAC码流到FLV文件

    AAC编码后数据打包到FLV很简单.1. FLV音频Tag格式                              字节位置    意义0x08,                         ...

  2. sql加强练习

    1.用一条SQL语句 查询出每门课都大于80分的学生姓名 name kecheng fenshu 张三 语文 81张三 数学 75李四 语文 76李四 数学 90王五 语文 81王五 数学 100王五 ...

  3. iphone UIScrollView缩放

    allImageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)]; allImageScrol ...

  4. mybatis重拾---部署官方demo

    学习一个框架,个人认为不是从什么start開始.而是从官方的demo開始,先将demo跑起来,了解到这个框架做了什么.能够实现那些功能.对框架有了一个总体的宏观概念! demo看得差点儿相同后再看官方 ...

  5. 一个简单的ajax对象

    function ajax(options) { //请求参数 options = { //类型 type: options.type || "Post", //地址 url: o ...

  6. Private Members in JavaScript

    Private Members in JavaScript Douglas Crockford www.crockford.com JavaScript is the world's most mis ...

  7. BZOJ4006 JLOI2015 管道连接(斯坦纳树生成森林)

    4006: [JLOI2015]管道连接 Time Limit: 30 Sec Memory Limit: 128 MB Description 小铭铭最近进入了某情报部门,该部门正在被如何建立安全的 ...

  8. www

    dddd int vec_rotate(char *vec,int rotdist, int length) { int i,j,k,times; char t; times = gcd(rotdis ...

  9. 网页title标题的闪动效果

    通过网页title来提示用户有新消息这个功能很常见,比如现在的微博,还有一些邮箱,这个功能都很常见. 显示信息数: <input type="text" id="t ...

  10. Git / Bower Errors: Exit Code # 128 & Failed connect

    今天第一次使用bower来安装插件,上来就报了这个错. 然后在google上查找,很多人都有做出回答,让执行如下 git config --global url.https://github.com/ ...