欢迎关注公众号: nullobject 。
文章首发在个人博客 https://www.nullobject.cn,公众号nullobject同步更新。
PTP/IP (PTP over IP) 是一个通过IP连接,建立在 Picture Transfer Protocol (PTP) 上的传输层
英文原版协议下载
0 说明
本文档由nullobject对应PTP-IP标准协议1.0版本进行学习整理,原版协议为英文版,学习时依靠自己理解和使用有道云翻译,对理解不到位、翻译有问题的地方麻烦批评指正。—— by nullobject in 2019-06-03 15:29
1 PTP-IP协议简介
1.1 目的
本文档描述了一个基于IP网络的ISO-15740/PIMA 1574:2000/图片传输协议(PTP)的实现。
PTP被设计用来提供与数字静止摄影设备的标准通信。该协议指定了标准的图像引用行为、操作、响应、事件、设备属性、数据集和数据格式,以确保互操作性,还提供了可选的操作和格式,以及扩展机制。
1.2 格式规范
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, “OPTIONAL” in this document are to be interpreted as described in “Key words for use in RFCs to Indicate Requirement Levels”[5].
1.3 参考
下表列举了本文档的参考资料:
ID/Description |
---|
[1] PTP protocol, PIMA 15740:2000 |
[2] Computer Networks, Andrew S. Tanenbaum, ISBN:0130661023, Prentice Hall Aug 09,2002 |
[3] UPnP Standard, http://www.upnp.org/resources/documents.asp |
[4] ZeroConf Standard, http://www.zeroconf.org |
[5] Formatting Conventions. http://www.faqs.org/rfcs/rfc21129.html |
1.4 手写字母缩写和缩写词
缩写 | 含义 |
---|---|
TCP | Transfer Control Protocol |
UDP | User Datagram Protocol |
IP | Internet Procotol |
PnP | Plug and Play |
PTP | Picture Transfer Protocol |
PTP-IP | IP Picture Transfer Protocol |
PIMA | Photographic and Imaging Manufacture Association |
DHCP | Dynamic Host Configuration Protocol |
v4LL | IPv4 Link-Local Address |
1.5 参与人员
- Petronel Bigioi – FotoNation Ireland
- George Susanu – FotoNation Ireland
- Alexei Pososin – FotoNation Ireland
- Denis McHugh – FotoNation Ireland
- Eran Steinberg – FotoNation US
- Yury Prilusky – FotoNation US
1.6 照片传输协议(“PTP”)条款
PTP规范定义了设备角色、操作、图像格式和其他相机特定的数据类型和结构。在PTP的TCP/IP实现中,所有术语和定义都按照PTP规范中定义的那样使用。
1.6.1 设备规则
从通信的角度来看,设备可以充当启动器设备(Initiator)或响应端设备(Responder),启动器设备相当于一个客户端,响应端设备相当于服务端。启动器设备是向响应端设备发起操作请求的设备。响应端设备则是能够响应这些操作请求的设备。一个设备可能只是一个启动器设备,或者只是一个响应端设备,或者两者兼备,但不能在同一个设备连接上同时担任两种角色。
操作请求只能由启动器设备发起;事件被响应端设备用于把有关它状态的改变通知启动器设备。
1.6.2 会话(Session)
根据PTP协议,会话被定义为两个设备之间的逻辑连接,操作和事件事务可以通过该逻辑连接进行通信。根据PTP规范,一个响应端设备可以支持多个并发会话,每个会话都有自己的状态。
当启动器设备请求OpenSession操作事务时将会打开一个会话,并且使用响应端设备发出的一个有效响应成功结束该请求。
会话将在启动器设备请求CloseSession操作事务时被关闭,并且使用响应端设备发出的一个有效响应成功结束该请求。当启动器设备和响应端设备之间的连接被关断开时会话也会被关闭(例如通信超时)。
大多数操作需要在一个开放会话上下文中执行。不过,不需要打开会话就可以通过GetDeviceInfo操作获取设备功能。
支持多会话的设备必须能够使它们彼此保持异步和不透明。
1.6.3 会话ID(SessionID)
通常,如果使用相同传输级别的通信通道,则会话ID旨在使响应端设备能够按适当的顺序分发来自不同启动器设备的请求。对于打开不同通信通道的传输,对于每个会话,不需要重新设置会话ID,因为响应端设备将能够处理多个会话。
PTP的PTP- IP传输实现不会将会话ID发送到响应端设备。响应端设备可以通过控制它允许的最大PTP- IP连接数来限制并发PTP会话的数量。
如果启动器设备的PTP-IP层发现响应端设备不接受新的PTP-IP连接,它将向PTP层发送传输特定的错误代码。在建立传输指定连接之后,启动端设备可以向远程响应端设备发出GetDeviceInfo和OpenSession请求。在这个阶段中,响应端设备可能返回一个设备繁忙(Device_Busy)的PTP错误作为对OpenSession的响应(如果响应端设备对它能够支持的并发PTP会话的数量有限制)。在这种情况下,启动端设备应该释放PTP连接,并稍后重试。
1.6.4 事务(Transactions)
事务是PTP协议中操作的基本单位,PTP协议规定的所有操作都基于事务进行。事务操作请求由启动器设备(Initiator)发起,传送到到响应端设备(Responder),在一个会话(Session)中,同一时间只能有一个事务操作在执行,操作事务在一个会话中默认是同步的。
一个事务通常由三个阶段组成:Operation Request、Operation Response、Data Phase,如下图:
取决于事务操作本身,Data Phase这一可选阶段可能不会存在于一个事务流程中,即事务只有Operation Request和Operation Response。而当事务中存在Data Phase时,数据可能从初始化器Initiator发送到响应设备Responder(即I–>R),或者反过来R–>I,但同一个操作中数据只能在一个方向上传输。
1.6.5 事务ID(TransactionID)
事务ID(TransactionID)用于在一个给定的会话中标识不同事务,与在PTP协议的第9.3.1项中定义的事务ID相同,是一个32位无符号整型数字。事务ID在给定的会话中是唯一且连续的数字序列,其范围从0x00000001到0xFFFFFFFE,0x00000000和0xFFFFFFFF作为保留值不被使用。
1.7 与PTP协议一致性
在PTP标准协议的7[1]节中,为底层传输层定义了这些需求。
- PTP标准协议 7.1节:断开事件。PTP协议的这一节要求传输层必须向上层的报告设备断开。这是通过PTP-IP 层生成设备断开通知来实现的。
- PTP标准协议 7.2节:稳定、无错误通道。PTP协议的这节要求需要可靠,无错误的通道。在PTP-IP中,这通过使用配置了Keep Alive选项的TCP连接来实现。
- PTP标准协议 7.3节:异步事件的支持。PTP要求支持异步事件,在PTP-IP中,事件连接被定义为用于传输异步事件,并且与命令/数据通道是异步的。
- PTP标准协议 7.4节:设备发现和枚举。PTP要求支持设备发现和枚举服务,在PTP-IP中,设备发现和枚举使用对IP网络可用的通用解决方案来实现,可以使用一个基于设备发现协议[5]的自定义UDP协议。
- PTP标准协议 7.5节:传输特定。PTP要求图像设备传输的实现符合相关机构发布的特定使用传输规范。本文档说明了如何使用位于TCP/IP协议栈上层的PTP-IP传输。
2 PTP-IP实现
2.1 PTP-IP协议模型
在PTP-IP的实现中,用户程序与PTP-IP层之间的通信基于PTP事务模型实现,参考PTP协议的9.3[1]节,该通信模型如下图:
本文档的目的在于制定和说明PTP-IP通信协议,应用程序和PTP-IP层(编程接口,API)之间交互的实现并不在本文档的内容范围内。本文档仅以互操作性的方式规定两个PTP-IP实体之间的通信。不过,PTP层(用户应用程序)和PTP-IP层之间的接口可能由以下基本类型组成:
-
操作请求(Operation Request)
每当进行请求操作时,启动器设备(Initiator)中的应用程序就会发送一个操作请求,随即该请求被响应端设备(Responder)接受。操作请求中通常包含一组与该操作相关的参数。
-
操作响应(Operation Responses)
每当接收到一个操作请求,响应端设备(Responder)会发送一个操作响应作为该操作请求的回应。对于启动器设备(Initiator)中应用程序发起的每个操作请求,都需要回复一个操作响应。操作响应中总是会包含其对应的操作请求的结果代码,并且可能会包含一组参数。
-
数据读入(Data-In)
数据读入(Data-In)是相对于用于应用程序而言的,即数据流向是从响应端设备(Responder)到启动器设备(Initiator)。
-
数据写出(Data-Out)
数据写出(Data-Out)的数据流与数据读入(Data-In)相反。
-
事件(Events)
PTP-IP中的事件是指有关响应端设备(Responder)的状态变更的通知,事件由响应端设备启动。
-
设备连接/断开(Device Connect/Disconnect)
设备的连接/断开是平台相关类型的事件。这两个事件并不直接在启动器设备和响应端设备之间通信,而是当检测到设备被连接/断开时由各自的PTP-IP层生成。
操作和事件两种事务的类型的定义在PTP协议文档的10.11、12 [1]节中可以找到,并且PTP协议在14 [1]节中为设备标准的一致性确定了一组操作和事件。
2.2 PTP-IP传输模型
PTP标准协议文档的7 [1]节定义了PTP标准传输需求,而PTP-IP则是基于使用TCP层作为传输层实现:
与PTP一样,PTP-IP也期望从其传输层获得可靠、稳定无错误的通信通道,而TCP(位于TCP/IP协议栈中)正是可以满足这些需求的自然传输层。TCP是一个基于流的传输层,它提供多个通信通道(TCP Connection)和无错误的数据传输。
在PTP-IP中,两个设备之间的所有通信都通过两个TCP连接(逻辑数据通道)进行:
由于事件本身具有异步性质,事件的数据包与操作/数据事务数据包分开分别通过两个单独的通道传输。
2.2.1 命令/数据连接(Command/Data TCP Connection)
PTP-IP的 命令/数据连接用于传输PTP操作请求、响应和数据事务,以及特定于PTP-IP的数据包。该连接由启动器设备(Initiator)建立,并标志本地及响应端设备(Responder)的IP地址和端口号。响应端设备(Responder)的IP地址和端口号通常是通过设备发现机制来确定。
2.2.2 事件连接(Event TCP Connection)
PTP-IP的事件连接作为启动器设备(Initiator)开启的与响应端设备(Responder)之间的第二个连接,用于传输PTP事件,以及特定于PTP-IP的数据包。与命令/数据连接相同,事件连接由启动器设备(Initiator)发起建立, 并标志本地和响应端设备(Responder)的IP地址和端口号,响应端设备(Responder)的IP地址和端口号通常是通过设备发现机制来确定。
2.2.3 传输通道管理
2.2.3.1 建立PTP-IP连接
在启动器设备(Initiator)与响应端设备(Responder)之间的通信中,每当需要这些传输通道时,启动器设备(Initiator)将负责发起与响应端设备(Responder)的PTP-IP/TCP连接。如前文所述,PTP-IP的传输通道使用TCP连接实现:一个通道用于命令/数据传输,另一个则用于事件传输。每个通道都会标志本地以及响应端设备(Responder)IP地址和端口号。从PTP-IP的通信模型中可以看到,启动器设备(Initiator)的PTP-IP实际上是一个TCP客户端,对应地响应端设备(Responder)的PTP-IP则是一个TCP服务器。响应端设备(Responder)轮询等待连接请求,并且预定义(或者动态分配)了一个TCP连接端口号.PTP-IP服务端默认端口号为15740。PTP-IP连接建立过程:
PTP-IP中的TCP连接应遵循上图所示顺序进行:
- 启动器设备(Initiator)发起命令/数据的TCP连接:指定响应端设备(Responder)的IP地址和端口号,并连接到响应端设备(Responder);
- TCP连接建立成功后,启动器设备(Initiator)立即发送一个Init Command Request包,数据包中需要包含启动器设备(Initiator)的唯一标识(GUID和启动器设备的用户友好名称),例如:
- 响应端设备(Responder)程序根据实际情况,回复启动器设备一个Init Command Ack包以告知启动器设备请求成功并且可以继续进行连接;或者回复Init Fail数据包表示请求失败,以告知启动器设备请求访问被拒绝,并且断开命令/数据的TCP连接,同时启动器设备接收到请求失败的回应后也应该断开相应的的命令/数据连接。
- 启动器设备(Initiator)接收到Init Command Ack包后,继续发起一个事件的TCP连接:指定响应端设备(Responder)的IP地址和端口号,并连接到响应端设备(Responder)。注意该连接与第1步中的连接是区别开的。
- 一旦连接建立成功,启动器设备(Initiator)立即发送一个Init Event Request包,数据包需要包含第4步骤中接收到的连接号(Connection Number)。响应端设备(Responder)需要根据这个连接号将命令/数据和事件两个TCP连接关联同一个PTP-IP连接和同一个PTP会话。
- 与步骤3类似,请求成功则回复一个Init Event Ack包,在响应端设备(Responder)资源不足时,回复Init Fail包告知启动端请求失败。
- 一旦启动器设备(Initiator)接收到步骤6中回传的Init Event Ack包则认为请求成功,此时PTP-IP连接真正建立完成,接着即可进行进一步的数据通信。
在第二个TCP连接(事件连接)建立失败的情况下,第一个TCP连接(命令/数据连接)需要被关闭,稍后启动器设备(Initiator)应再次尝试建立PTP-IP连接。建议每次创建PTP-IP连接的时间间隔为30s。
2.2.3.2 传输通道配置
根据PTP协议7 [1]节,PTP-IP层要求传输通道可靠、无错误。这种传输通道可以通过正确配置TCP连接来实现。
PTP-IP的TCP连接应该使用一下选项创建:
- Keep Alive 选项:启动器和响应端需要同时需要同时开启这个选项,以确保两端的TCP实体在非活跃时期能够维持连接。开启这个选项后,启动器和响应端各自的TCP栈会通过TCP协议特定的方式来检查所配对的设备是否仍旧能够响应。这种检查方式是在TCP层进行,对上层的PTP-IP来说是透明的。
- 禁用Nagle算法:需要在启动器和响应端程序的TCP/IP协议栈上禁用Nagle算法,以避免在传输命令代码和响应时出现不必要的延迟。
总的来说就是需要设置如下选项(Qt为例):
// 禁用Nable算法
mTcpSocket->setSocketOption(QAbstractSocket::SocketOption::LowDelayOption,1);
// 开启Keep Alive选项
mTcpSocket->setSocketOption(QAbstractSocket::SocketOption::KeepAliveOption,1);
2.2.3.3 关闭PTP-IP连接
当不再需要PTP-IP时,由启动器设备(Initiator)关闭连接。当启动器设备(Initiator)或者响应端设备(Responder)在打开的传输通道上发生错误而导致这些通道不稳定时,也应关闭PTP-IP连接。关闭PTP-IP连接时两个TCP连接(命令/数据连接和事件连接)都必须要关闭。
2.3 传输的数据包类型
本节主要介绍用于在启动器设备(Initiator)和响应端设备(Responder)间通信的一组数据包类型。PTP-IP的数据包类型相当于PTP协议中定义的操作请求(Operation Request)、响应(Response)、数据(Data)和事件(Event)事务类型。PTP-IP数据包中的所有多字节值都使用小端(Little-Endian)格式表示,通常一个PTP-IP数据包的格式如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
Payload | 根据Length计算 | ? |
- 长度(Length):4字节,长度参数决定了包含包头在内的整个数据包的大小;
- 包类型(Packet Type):4字节,该字段标志了数据包的类型,该参数有下列可选的值:0x0000NNNN*表示隐藏值。
Value | Description |
---|---|
0x00000000 | 保留值 |
0x0000NNNN* | Init Command Request Packet |
0x0000NNNN* | Init Command Ack |
0x0000NNNN* | Init Event Request Packet |
0x0000NNNN* | Init Event Ack Packet |
0x0000NNNN* | Init Fail Packet |
0x0000NNNN* | Operaqion Request Packet |
0x0000NNNN* | Operation Response Packet |
0x0000NNNN* | Event Packet |
0x0000NNNN* | Start Data Packet |
0x0000NNNN* | Data Packet |
0x0000NNNN* | Cancel Packet |
0x0000NNNN* | End Data Packet |
0x0000NNNN* | Probe Request Packet |
0x0000NNNN* | Probe Response Packet |
0x0000NNNN* - 0xFFFFFFFF | 保留值 |
- 负载(Payload):包含协议更上层的或者是传输特定的数据。
2.3.1 Init Command Request Packet
该数据包在命令/数据传输通道被建立后立即被启动器设备(Initiator)发送。该数据包通过命令/数据连接传输,用于通知响应端设备(Responder)对启动器进行标识,从而使响应端设备(Responder)能够实现过滤机制。数据包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
Initiator GUID | 16 | UINT8 |
Initiator Friendly Name | Variable | UINT16 |
Initiator Protocol Version | 4 | UINT32 |
- Initiator GUID:16字节,启动器设备的全局唯一标识符;
- Initiator Friendly Name:启动器设备的用户友好名称,该字段是一个包含启动器设备描述信息的Unicode字符串,该字串通常用于响应端设备的UI显示上(以确认或拒绝来自给定启动器设备的连接请求);
- Initiator Protocol Version:4字节,启动器设备端实现的协议版本号。该字段由一个主版本号(高16位)和一个子版本号(低16位)组成。该字段应该被设置成第3节中定义的BINARY PROTOCOL VERSION。
- 启动器设备的GUID和响应端设备的GUID可用于进行设备绑定。若启动器设备的GUID的16个字节全由0xFF组成,则表示该启动器设备是一个匿名设备,此时由响应端设备决定是否允许连接。更多信息参考附录5.3。
- 启动器设备的用户友好名称是一个以空(NULL)字符结尾的Unicode字符串。包括结尾的空字符,其最大长度位40个字节。不使用该字段时,必须使用一个空(NULL)字符填充该字段。
数据包示例:
对应地:
- 30 00 00 00:第0~3字节表示Length字段
- 01 00 00 00:第4~7字节表示Packet Type字段
- fc 47 f8 4e 30 97 ee 64 1c 26 38 ae b0 1a 9e ac:第8~23字节表示Initiator GUID字段
- 44 00 53 00 43 00 2d 00 52 00 58 00 30 00 4d 00 32 00 00 00:第24~(Length-4-4-16-4-1)字节表示Initiator Friendly Name字段
- 00 00 01 00:最后4字节表示Initiator Protocol Version字段。
2.3.2 Init Command ACK Packet
该数据包由响应端设备(Responder)回传给启动器设备,以响应启动器设备发送的Init Command Request Packet,并为接下来的PTP-IP会话分配一个连接号(Connection Number),该数据包在命令/数据连接上传输。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
Connection Number | 4 | UINT32 |
Responder GUID | 16 | UINT6 |
Responder Friendly Name | Variable | UINT16 |
Responder Protocol Version | 4 | UINT32 |
- Connection Number:连接号,是响应端设备生成的用于关联所有属于同一个PTP会话的TCP连接通道的唯一值。
- Responder GUID:响应端设备的GUID。
- Responder Friendly Name:响应端设备的用户友好名称,可用于启动器设备端的UI显示。
- Responder Protocol Version:响应端设备实现的协议版本号。该字段由一个主版本号(高16位)和一个子版本号(低16位)组成。该字段应该被设置成第3节中定义的BINARY PROTOCOL VERSION。
- 响应端设备的用户友好名称是一个以空(NULL)字符结尾的Unicode字符串。包括结尾的空字符,其最大长度位40个字节。不使用该字段时,必须使用一个空(NULL)字符填充该字段。
- 连接号在启动器设备和响应端设备连接被建立的期间保持有效。一旦响应端设备成功关联属于同一个PTP-IP连接的两个TCP连接,连接号即可被重新使用。
实际该数据包结构看起来如下:
对应地:
- 34 00 00 00:第0~3字节表示Length字段
- 02 00 00 00:第4~7字节表示Packet Type字段
- 01 00 00 00:第8~11字节表示Connection Number字段
- 00 00 00 00 00 00 00 00 ff ff 10 98 c3 d1 5f 45:第12~27字节表示Responder GUID字段
- 44 00 53 00 43 00 2d 00 52 00 58 00 30 00 4d 00 32 00 00 00:第28~(Length-4-4-4-16-4-1)字节表示Responder Friendly Name字段
- 00 00 01 00:最后4字节表示Responder Protocol Version字段。
2.3.3 Init Event Request Packet
命令/数据连接被成功建立后,该数据包被启动器设备发送至响应端设备用于建立事件连接。启动器设备在接收到一个有效的Init Command Ack Packet数据包后,立即建立事件的TCP连接并发送Init Event Request Packet数据包,包中携带的连接号即前面步骤中接收到的在Init Command Ack数据包中返回的连接号。Init Event Request数据包通过事件连接传输。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
Connection Number | 4 | UINT32 |
- Connection Number:连接号,从Init Command Ack Packet包数据中获得。
数据包示例:
对应地:
- 0c 00 00 00:第0~3字节表示Length字段
- 03 00 00 00:第4~7字节表示Packet Type字段
- 01 00 00 00:第8~11字节表示Connection Number字段
2.3.4 Init Event ACK Packet
该数据包由响应端设备(Responder)通过事件连接通道回传给启动器设备,以告知启动器设备PTP-IP连接建立成功。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
数据包示例:
对应地:
- 08 00 00 00:第0~3字节表示Length字段
- 04 00 00 00:第4~7字节表示Packet Type字段
2.3.5 Init Fail Packet
初始化失败数据包。当PTP-IP连接建立失败时,该数据包由响应端设备(Responder)回传给启动器设备,以告知启动器设备连接建立失败及失败原因,失败原因被记录在Reason字段。接收到该数据包之后,启动器设备必须关闭先前步骤中建立的命令/数据连接。该数据包发出后,响应端设备亦应关闭相应的PTP-IP连接(由启动器设备发起的被拒绝的TCP连接)。Init Fail Packet可以通过任意的TCP连接传输。更多有关PTP-IP连接的建立可以参考PTP-IP连接一节内容。
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
Reason | 4 | UINT32 |
Reason字段包含了连接拒绝的错误码,该字段定义的错误码有以下几种:
- 0x0000NNNN*:FAIL_REJECTED_INITIATOR,表示响应端设备实现了一个设备绑定的机制,但请求连接的启动器设备不在允许的设备集合内。参考附录5.3了解绑定机制详情。
- 0x0000NNNN*:FAIL_BUSY,表示响应端设备繁忙:响应端设备的活动连接数过多。启动器设备可以稍后再尝试连接。
- 0x0000NNNN*:FAIL_UNSPECIFIED,其他原因。
2.3.6 Operation Request Packet
操作请求数据包。该数据包在PTP-IP协议中用于传输在PTP标准协议9.3.2 [1]节定义的PTP操作请求。PTP-IP Operation Request Packet由启动器设备发送至响应端设备,并通过命令/数据通道传输。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
Data Phase Info | 4 | UINT32 |
Operation Code | 2 | UINT16 |
TransactionID | 4 | UINT32 |
Parameter1 | 4 | UINT32 |
Parameter2 | 4 | UINT32 |
Parameter3 | 4 | UINT32 |
Parameter4 | 4 | UINT32 |
Parameter5 | 4 | UINT32 |
-
Data Phase Info:指示下一个数据阶段是数据写(data out)阶段还是数据读/数据(data in/no)阶段,该字段值被定义为下列几种:
- 0x0000NNNN*:无数据或数据读(data in/no)阶段:启动器设备不知道响应端设备是否会提供一些数据或者提供一个响应;
- 0x0000NNNN*:数据写(data out)阶段
- 0x0000NNNN*:未知的数据阶段
- Operation Code:操作码,包含定义在PTP标准协议第10.2和10.3 [1]节的PTP操作码。
- TransactionID:事务ID,它在当前连接的响应端设备的开放会话上下文中是唯一的,如PTP第9.3.1 [1]节中定义。TransactionID是一个从0x00000000到0xFFFFFFFF的连续数值。0x00000000作为特殊的值,只能被用于OpenSession或GetDeviceInfo两个操作请求,每次当此参数不适用于包时,必须使用另一个特殊值0xFFFFFFFF。
- Parameter 1~5:这些字段包含特定于操作的参数,这些参数的解释取决于操作码(Operation Code)参数,一个操作最多可以容纳5个参数。这些参数的使用方式定义在PTP标准协议的10.1和10.4 [1]节。
- 如果Data Phase Info字段被设置为Data Out Phase,则在发送该数据包后接着必须要发送一个Start Data Packet包。
- 如果启动器设备需要发送空数据对象到响应端设备,有两个选项可选:1.将Data Phase Info字段设置为No data or data in phase,在这情况下响应端设备将会直接回应一个Operation Response Packet包,而不会等待Data Packet;2.将Data Phase Info字段设置为Data out Phase.在这种情况下,数据写阶段(data out phase)必须只包含一个Start Data Packet包,并将该包的Total Data Length字段设置为0x00000000,并且启动器设备必须不能发送后续的End Data Packet数据包。
实际该数据包结构如下:
对应地:
- 16 00 00 00:第0~3字节表示Length字段
- 06 00 00 00:第4~7字节表示Packet Type字段
- 02 00 00 00:第8~11字节表示Data Phase Info字段
- 05 92:第12~13字节为Operation Code字段
- 06 00 00 00:第14~17字节为Transaction ID字段
- 0e 50 00 00:第18~21字节为Parameter 1字段
2.3.7 Operation Response Packet
操作响应数据包。该数据包在PTP-IP协议中用于传输在PTP标准协议9.3.4 [1]节定义的PTP操作响应。PTP-IP Operation Response Packet数据包由响应端设备通过命令/数据通道回应给启动器设备。操作响应数据包仅在需要指示操作请求事务已经结束并且需要传递操作结果时才由响应端设备发送给启动器设备。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
Response Code | 2 | UINT16 |
TransactionID | 4 | UINT32 |
Parameter1 | 4 | UINT32 |
Parameter2 | 4 | UINT32 |
Parameter3 | 4 | UINT32 |
Parameter4 | 4 | UINT32 |
Parameter5 | 4 | UINT32 |
- Response Code:响应码,包含定义在PTP标准协议第11.1和11.3 [1]节的操作响应码。
- TransactionID:事务ID,它在连接到响应端设备的开放会话上下文中是唯一的,如PTP第9.3.1[11]节中定义。TransactionID是一个从0x00000001到0xFFFFFFFE的连续数值。0x00000000作为特殊的值,只能被用于OpenSession或GetDeviceInfo两个操作请求,每次当此参数不适用于包时,必须使用另一个特殊值0xFFFFFFFF。
- Parameter 1~5:这些字段包含特定于操作的参数,这些参数的解释取决于生成响应的操作以及特定的响应代码值。一个操作响应的数据包最多可以容纳5个参数。这些参数的使用方式定义在PTP标准协议的9.3.4 [1]节。
实际该数据包结构如下:
对应地:
- 0e 00 00 00:第0~3字节表示Length字段
- 07 00 00 00:第4~7字节表示Packet Type字段
- 01 20:第8~9字节表示Response Code字段
- 05 00 00 00:第10~13字节为Transaction ID字段
2.3.8 Event Packet
事件数据包。该数据包用于传输在PTP标准协议12.2 [1]节中定义的事件。这些事件由响应端设备通过事件连接通道发送给启动器设备,以通知启动器设备响应端的状态变更。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
Event Code | 2 | UINT16 |
TransactionID | 4 | UINT32 |
Parameter1 | 4 | UINT32 |
Parameter2 | 4 | UINT32 |
Parameter3 | 4 | UINT32 |
- Event Code:事件码,包含定义在PTP标准协议第12.3和12.4 [1]节的事件码。
- TransactionID:事务ID,它在当前连接到响应端设备的开放会话上下文中是唯一的,其定义在PTP标准协议的9.3.1 [1]节。如果事件数据包对应于先前发起的事务,则该字段应该被设为操作所对应的事务ID。如果事件没有指定于特定的事务,则该字段应设为0xFFFFFFFF。
- Parameter 1~3:这些字段包含特定于事件的参数。这些参数的解释却决于事件码(Event Code)字段。一个Event Packet数据包最多能容纳3个参数,有关这些参数的使用说明定义在PTP标准协议的12.5 [1]节。
2.3.9 Start Data Packet
开始数据传输数据包。该数据包在PTP-IP中用于标识数据传输的开始。其通过命令/数据通道传输,可以由任意一设备端发送,另一端接收。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
TransactionID | 4 | UINT32 |
Total Data Length | 8 | UINT64 |
- Total Data Length:包含即将在数据读(data in)阶段或数据写(data out)阶段中被传输的数据大小。特定的值0xFFFFFFFFFFFFFFFF表示在数据阶段的开始并不知道数据的大小,该值的使用仅限于传输对象的大小未知的情况(例如:传输流数据)。
数据包示例:
其中:
- 14 00 00 00:第0~3字节表示Length字段
- 09 00 00 00:第4~7字节表示Packet Type字段
- 01 00 00 00:第8~11字节表示Transaction ID字段
- 08 00 00 00 00 00 00 00:第12~19字节为Total Data Length字段
2.3.10 Data Packet
该数据包在PTP-IP中用于传输数据。Data Packet包只在数据阶段使用,且可以由当前数据流方向上的任意一端发送,另一端接收:在数据读(data-in)阶段由响应端设备发送给启动器设备;在数据写(data-out)阶段由启动器设备发送给响应端设备。Data Packet数据包走的是命令/数据的连接通道。
由于TCP传输是无错误、基于流的协议,通常不需要对大型的数据包进行拆包和粘包操作。不过可以使用基本的碎片机制来实现一个简单的数据传输取消机制,Data Packet不需要进行错误校验。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
TransactionID | 4 | UINT32 |
Data Payload | ? | UINT8 |
- Data Payload:包含数据包中需要传输的数据。
数据包示例:
其中:
- 14 00 00 00:第0~3字节表示Length字段
- 0a 00 00 00:第4~7字节表示Packet Type字段
- 01 00 00 00:第8~11字节表示Transaction ID字段
- 00 00 00 00 00 00 00 00 0c 00 00 00 0c 00 00 00 01 00 00 00 0e 00 00 00 07 00 00 00 01 20 01 00 00 00:第12~N字节为Data Payload字段。
2.3.11 End Data Packet
终结数据传输的数据包。End Data Packet数据包在PTP-IP中用于标识数据阶段的结束,该数据包中也可以携带一些有用数据。该数据包只在一个事务的数据阶段使用,可以由数据流方向上的任意一端发送,另一端接收:在数据读(data-in)阶段由响应端设备发送给启动器设备;在数据写(data-out)阶段由启动器设备发送给响应端设备。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
TransactionID | 4 | UINT32 |
Data Payload | ? | UINT8 |
- Data Payload:如果数据包中包含有数据则放在这个字段。
数据包示例:
其中:
- 10 00 00 00:第0~3字节表示Length字段
- 0c 00 00 00:第4~7字节表示Packet Type字段
- 06 00 00 00:第8~11字节表示Transaction ID字段
- 02 00 01 00:第12~(Length-4-4-4)字节为Data Payload字段。
2.3.12 Cancel Packet
Cancel Packet数据包用于取消传输事务,由启动器设备发送至响应端设备。该数据包在命令/数据连接通道和事件连接通道上发送。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
TransactionID | 4 | UINT32 |
2.3.13 Probe Request Packet
心跳包。该数据包可用于PTP-IP的启动器设备和响应端设备,以检查对等设备是否仍然有效。当接收到该数据包时,设备必须立即响应一个Probe Response Packet数据包。如果在一段合理的时间内没有收到响应,则发出该数据包的设备将关闭与对端设备的PTP-IP会话。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
数据包示例:
其中前、后四个字节分别为Length字段和Packet Type字段。
使用该数据包时应要注意控制发送的频率以避免造成局域网过载:
- 启动器设备发送至响应端设备(I–>R):建议这个包只在PTP事务中使用(例如,当发出格式命令时,如果存储介质很大,响应时间可能会很长),以便检查响应端设备是否仍然处于活跃状态。
- 响应端设备发送至启动器设备(R–>I):建议仅当响应端设备接收到一个新的PTP-IP会话的请求,而另一个或多个其他会话处于活动状态时,才使用此包。在这种情况下,响应端设备可以检查现有的PTP-IP连接是否仍然处于活动状态。
- 建议在发送Probe Request Packet数据包和接收Probe Response Packet包之间设置10秒的超时时间。
2.3.14 Probe Response Packet
心跳包的回应数据包。该数据包可用于PTP-IP的启动器设备和响应端设备,作为另一端的Probe Request Packet请求的响应。当接收到一个Probe Request Packet请求时应当立即回复这个数据包。
包结构如下:
Field | Size[Bytes] | Data Type |
---|---|---|
Length | 4 | UINT32 |
Packet Type | 4 | UINT32 |
数据包示例:
其中前、后四个字节分别为Length字段和Packet Type字段。
2.4 会话的实现
由启动器设备在PTP层发起的新会话请求将生成两个新的TCP连接,这两个连接即对应于PTP-IP层的命令/数据(Command/Data)连接和事件(Event)连接。这两个TCP连接足够用来唯一标识其所属的会话,因此不需要将会话ID(SessionID)作为独立的值从启动器设备发送到响应端设备。
2.5 设备断开和网络丢失处理
在PTP-IP协议中,对设备的断开或者网络丢失的检测基于以下一些标准:
- 网络层通知应用程序有关网络连接断开(例如媒体断开连接)的功能。
- 任意一个PTP-IP连接通道丢失(命令/数据通道或事件通道),例如socket被破坏。
- 任意一个PTP-IP通道传输超时。
2.6 数据流控制
为了防止一个设备在事务的数据阶段用数据重载另一个设备,通常会实现一个数据流控制机制。不过在PTP-IP中不需要实现这样的机制,因为底层的TCP层会执行流控制操作。
TCP层在两个级别实现流控制:接收设备和网络,避免在低速接收和低速网络下数据泛滥。因此,在PTP-IP中采用TCP连接作为通信通道,直接解决了流量控制的问题。
2.7 事务取消机制
有两种可能取消事务的情况:启动器设备请求取消或者响应端设备请求取消。
2.7.1 启动器设备产生的取消
2.7.1.1 数据写阶段
启动器设备为了取消正在进行的数据写阶段传输,必须在命令/数据通道和事件通道上发出一个Cancel Packet数据包,并停止任何正在命令/数据通道上的数据传输。当响应端设备在命令/数据通道或事件通道上收到Cancel Packet数据包时,必须尽可能快地中断并取消正在进行的事务,同时读取和丢弃所有属于当前事务(如果有)的剩余的数据包,并且向启动器设备回应一个附带有Transaction_Cancelled响应码的Operation Response Packet数据包。
2.7.1.2 数据读阶段
启动器设备为了取消正在进行的数据读阶段传输,必须在命令/数据通道和事件通道上发出一个Cancel Packet数据包。响应端设备在命令/数据通道或事件通道上收到Cancel Packet数据包时,必须尽可能快地中断并取消正在进行的事务,并且向启动器设备回应一个附带有Transaction_Cancelled响应码的Operation Response Packet数据包。
2.7.1.3 其他事务阶段
启动器设备可以通过在命令/数据通道和事件通道上发出一个Cancel Packet数据包以在事务的任意阶段退出事务。如果取消的是当前的事务,则响应端设备必须回应一个附带有Transaction_Cancelled响应码的Operation Response Packet数据包。
2.7.2 响应端设备产生的退出
2.7.2.1 数据写阶段
响应端设备为了取消正在进行的数据写阶段传输,必须发送一个附带有Transaction_Cancelled或者其他标识数据传输中断原因的响应码的Operation Response Packet数据包。然后,响应端设备必须读取和丢弃所有属于当前事务的在命令/数据通道中的Data Packet数据包。
2.7.2.2 数据读阶段
响应端设备为了取消正在进行的数据读阶段传输,必须在命令/数据通道上发送一个Operation Response Packet数据包,并且附带Transaction_Cancelled响应码或其他标识数据传输中断原因的响应码。
2.7.2.3 其他事务阶段
响应端设备可以通过发送附带Transaction_Cancelled响应码或其他标识数据传输中断原因的响应码的Operation Response Packet以在事务的任意阶段退出事务。
2.7.3 异步操作退出机制
启动器设备为了取消一个异步操作,必须同时在命令/数据通道和事件通道发送一个包含该异步操作所属的事务ID的Cancel Packet数据包,启动器设备可以在任意时候发送这些数据包。
响应端设备将以PTP事件(例如Capture Complete event)结束操作。解释取消请求的逻辑由响应端设备的应用层负责。
3 协议版本
该PTP-IP规范的二进制协议版本(BINARY PROTOCOL VERSION)是0x00010000(1.0版)。二进制协议版本由一个主要数字(高16位表示)和一个次要数字(低16位表示)组成。这个数字将增加,以表示较新的协议版本,方法如下:
- 次要版本进行了增加,以反映协议规范中的次要更改。实现新次要版本的设备必须完全支持同一主要版本的所有次要版本。
- 主要版本增加了,以反映协议规范中的主要更改。新协议规范可能与主号码较小的旧规范版本不兼容。
4 PTP-IP端口
如果没有实现设备发现协议,则每一个响应端设备和启动器设备应该通过以下端口号来初始化:
Port Name | Port No. | Type | Description |
---|---|---|---|
PTP-IP service | 15740 | TCP | 响应端设备等待TCP连接的默认端口,该端口由IANA批准。 |
5 附录
5.1 地址配置
PTP-IP协议的基础是TCP/IP协议,该协议的关键是寻址机制。响应端设备和启动端程序都将获得有效的IP地址。获取有效IP地址的方法有以下几种:
- 手动配置: IP地址和其他网络属性由用户手动配置,以反映图像设备将在其中工作的局域网的拓扑结构和地址模式;
- 基于DHCP配置:图像设备应实现一个DHCP客户端,DHCP客户端将自动从网络中的DHCP服务器获取IP地址。
- IPv4链路本地地址(v4LL)的动态配置:一个描述了一种在TCP/IP局域网上自动自配置网络设备的机制,而无需设置DHCP服务器的标准。
为了处理设备的TCP/IP属性配置,建议执行以下步骤:
- 如果属性是手动配置的,则使用该配置;
- 否则设备应使用DHCP协议获取IP地址以及其他配置参数(设备需要实现一个DHCP客户端);
- 如果网络中没有DHCP服务器,则可以部署v4LL动态配置。
5.2 设备发现和枚举
在PTP-IP中,启动器设备可以通过以下几种方式配置连接到响应端设备的地址:
- 手动配置:启动器设备将手动配置它可以连接的响应端设备的一个或一组地址。启动器设备会尝试根据IP地址建立一个PTP-IP连接,如果连接成功则说明响应端设备存在,此时可以建立一个PTP会话。
- Zeroconf:一族提供自动配置、设备和服务发现的协议和建议,在IETF Zeroconf Working Group.[4]中发表。
- UPnP:一组发表在UPnP Forum[3]用于简化设备配置、服务发现和调用的协议。仅可以使用该协议的设备和服务发现功能。
- 其他设备发现机制。
PTP规范第7.4条要求从其传输中支持设备发现和枚举。因此,PTP-IP 层应该至少实现以上这些服务中的一种。
不管使用什么服务发现和枚举,我们建议将设备的GUID作为广播包的一部分,这样启动端设备就能够过滤(如果需要的话)特定的设备,并生成选择性通知。
5.3 设备绑定和认证
认证并不是PTP-IP层的职责。如果需要身份验证,则应该依赖于底层网络(物理/数据链路层)中可用的解决方案。设备绑定可以依赖于底层网络可用的机制或者基于PTP-IP层提供的机制在应用层实现,如下:
PTP-IP上下文中每一个设备都需要由一个可被用于设备绑定的全局唯一的标识:GUID(16字节的唯一数字)。对于这些设备,PTP-IP层提供了一个允许启动器设备和响应端设备互相交换GUID的机制。这进而允许应用层实现设备级访问控制(例如,一个新设备到达并被网络发现,该设备只能接受来自已知启动器设备的的选择性连接,或者只能启动到已知响应端设备的连接)。
无论使用什么服务发现和枚举方法,都建议将设备的GUID作为广播包的一部分,这样启动端设备就能够过滤(如果需要的话)特定的设备,并生成选择性通知。
5.4 数据安全
本节不属于PTP-IP协议的范围。数据安全将依赖于底层网络(物理/数据链路层)中可用的解决方案。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。