一直对ipmsg(飞鸽传书)这个软件比较有兴趣,想自己看它的协议并实现一下。现在把协议比较核心的部分讲一下, 该协议使用两个端口,一个udp端口主要负责接受消息发送消息,tcp端口主要负责接受跟文件传输相关的消息以及传输文件数据。
首先是用户的发现,在程序刚启动时会在值定的广播地址广播含有IPMSG_BR_ENTRY命令的报文具体的报文格式如下
versionno:packetno:sender_name:sender_host:command_no:additional_section,
报文使用的全是字符表示,所以一个简单的发送消息的报文如下"1:100:shirouzu:jupiter:32:hello"
当所在广播地址范围内的主机受到该消息后,如果在该用户并没在用户名单中,把新用户加入到用户名单,并向发送广播的主机回复一条IPMSG_ANSENTRY命令的报文,使得自己也被对方主机加入到用户名单。
接下来就是收发消息了,收发消息主要使用下面的几个命令IPMSG_SENDMSG, IPMSG_RECVMSG,
有几个选项可以支持收到消息后发送确认和支持附加文件传输的功能。发送消息使用的报文格式和上面的格式一样,不同的地方就是把command域和
addditional_section分别变为发送命令或接受命令和要发送的消息。
再下面就是使用最多的传输文件和文件的功能了。下面拿一个文件和文件夹传输的例子来说明这部分的工作原理。发送文件和文件夹首先发送方只要在发送消息的命
令中加上IPMSG_FILEATTACHOPT这个选项,并在上面提到的additional_section后面加上要发送的文件活文件夹的属性字段
给接受方,文件相关的附属属性字段格式如下:
fileId:filename:size:mtime:fileattr[:extend-attr=val1[,val2..]]:\a:fileId...
其中size, mtime, fileattr这三个字段都是以16进制形式来表示的, fileattr字段可以表示该文件是普通文件还是文件夹
当接受方要下载文件时,向发送方的tcp监听端口发送IPMSG_GETFILEDATA命令消息,并在消息的additional_section把下
面字段加上packetId:fileID:offset(也是用16进制表示),发送方收到消息后,进行验证通过后,就开始实际的文件传输。这是发送和
传输普通文件,当传输整个目录文件数据时,发送方向接受方发送的数据格式要特别一些,具体格式如下:
header-size:filename:file-size:fileattr[:extend-attr=val1,[]]:contents-data
next-header-size:filename....
除了filename和contents-data其它域都使用16进制表示
下面拿个实例来说明一下:
发送方为A, 接受方为B, 只显示用跟文件传输相关的域,传输目录g2ipmsg,该目录下的结构如下
g2ipmsg
|-- AUTHORS
|
|-- pixmaps
| |-- ipmsg.png
|-- po
| |-- ChangeLog
|-- sounds
| `-- g2ipmsg.ogg
|-- src
| |-- Makefile
仅列出部分文件,下面有po, pixmaps, sounds, src这四个目录
packetId fileId:fileName:fileattr
A->B 1 1 src IPMSG_FILE_DIR
command packetId fileid filename
B->A IPMSG_GETFILEDATA 1 1 src
filename filesize fileattr
A->B src 0 IPMSG_FILE_DIR
当接受方B检测到fileattr是目录的话,知道接下来接受的文件在该目录之下,所以
应当创建该目录,并把工作目录切该目录下
filename filesize fileattr
A->B null 0 IPMSG_RETPARENT
当B接受上面的消息后,知道正在下载的目录的数据已经下载完毕,要切换到父目录
进行其它目录活文件的下载
上面只是对最核心的几个命令进行了说明,感兴趣的可以去看一下官方的协议说明文档
阅读(1354) | 评论(0) | 转发(0) |