- 浏览: 1504588 次
- 性别:
- 来自: 南京
文章分类
- 全部博客 (419)
- XMPP (19)
- Android (180)
- Java (59)
- Network (4)
- HTML5 (13)
- Eclipse (9)
- SCM (23)
- C/C++ (4)
- UML (4)
- Libjingle (15)
- Tools&Softwares (29)
- Linphone (5)
- Linux&UNIX (6)
- Windows (18)
- Google (10)
- MISC (3)
- SIP (6)
- SQLite (5)
- Security (4)
- Opensource (29)
- Online (2)
- 文章 (3)
- MemoryLeak (10)
- Decompile (5)
- Ruby (1)
- Image (1)
- Bat (4)
- TTS&ASR (28)
- Multimedia (1)
- iOS (20)
- Asciiflow - ASCII Flow Diagram Tool.htm (1)
- Networking (1)
- DLNA&UPnP (2)
- Chrome (2)
- CI (1)
- SmartHome (0)
- CloudComputing (1)
- NodeJS (3)
- MachineLearning (2)
最新评论
-
bzhao:
点赞123!
Windows的adb shell中使用vi不乱码方法及AdbPutty -
wahahachuang8:
我觉得这种东西自己开发太麻烦了,就别自己捣鼓了,找个第三方,方 ...
HTML5 WebSocket 技术介绍 -
obehavior:
view.setOnTouchListenerview是什么
[转]android 一直在最前面的浮动窗口效果 -
wutenghua:
[转]android 一直在最前面的浮动窗口效果 -
zee3.lin:
Sorry~~
When I build "call ...
Step by Step about How to Build libjingle 0.4
From:
http://bbs.7boo.com.cn/thread-1940-1-1.html
XMPP协议之Socket5 Bytestream文件传输
SOCK5流协商的建立一部分通过XMPP XML流,一部分通过一个独立的socket
实际的文件传输发生在创建的socket上。
第一步:
[发送端] 发送SI(流协商)包A
A:
<iq type='set' id='gaim8215f9ef' [email=to=]to='test@dd.antkingdom.com/Exodus'[/email]>
<si xmlns='http://jabber.org/protocol/si' id='gaim8215f9f0' profile='http://jabber.org/protocol/si/profile/file-transfer'>
<file xmlns='http://jabber.org/protocol/si/profile/file-transfer' name='backup.txt' size='2043'/>
<feature xmlns='http://jabber.org/protocol/feature-neg'>
<x xmlns='jabber:x:data' type='form'><field var='stream-method' type='list-single'>
<option><value>http://jabber.org/protocol/bytestreams</value></option>
</field>
</x>
</feature>
</si>
</iq>
[接收端] 接收A: 发送SI响应包B
B:
<iq id="gaim8215f9ef" to="[email=jjl@dd.antkingdom.com/Home]jjl@dd.antkingdom.com/Home[/email]" type="result">
<si id="gaim8215f9f0" xmlns="http://jabber.org/protocol/si">
<feature xmlns="http://jabber.org/protocol/feature-neg">
<x type="submit" xmlns="jabber:x:data">
<field var="stream-method"><value>http://jabber.org/protocol/bytestreams</value></field>
</x>
</feature>
</si>
</iq>
第二步:
[发送端] 接收B
创建socket,绑定一个地址,并监听(记下IP与端口号),等待连接
构造出如下的bytestream包C,发送包C
C:
<iq type='set' id='gaim8215f9f1' [email=to=]to='test@dd.antkingdom.com/Exodus'[/email]>
<query xmlns='http://jabber.org/protocol/bytestreams' sid='gaim8215f9f0'>
<streamhost [email=jid=]jid='jjl@dd.antkingdom.com/Home'[/email] host='192.168.100.1' port='6642'/>
</query>
</iq>
[接收端] 接收C:
创建一个socket, connect C包中指定的host与port
开始socket 5协商
socket 5协商完毕,发送bytestream响应包D
D:
<iq [email=from=]from='test@dd.antkingdom.com/Exodus'[/email] type='result' [email=to=]to='jjl@dd.antkingdom.com/Home'[/email] id='gaim8215f9f1'>
<query xmlns='http://jabber.org/protocol/bytestreams' sid='gaim8215f9f0'>
<streamhost-used [email=jid=]jid='jjl@dd.antkingdom.com/Home'/[/email]>
</query>
</iq>
第三步:
[发送端] 接收D
开始文件传输
Socket 5协商过程
一、[接收端]发送5,1,0
二、[发送端]接收到5,1,0,发送5,0
三、[接收端]接收到5,0,发送5,1,0,3+digest长度+0+0
注:digest是通过sessionID, 流发起者,流接收者,通过哈希算法得到的一个字符串
四、[发送端]接收到5,1,0,3+digest长度+0+0,发送5,0,0,3+digest长度+0+0
五、socket 协商完毕,建立了P2P的连接,下面通过这个连接的socket就可以进行文件传输了。
jabber/XMPP文件传输的一些情况
1 jabber/XMPP文件传输的一些情况
大家知道,Jabber/XMPP是一种 XML流技术,解决的问题主要是即时消息和出席信息,XML流技术并不适用于大数据量的传输。
即时通信应用中,消息和出席信息的问题相对是比较简单和容易实现的,XMPP的在这方面的长处在于两点:
- 使用了XML流技术,XML天然的结构化和可扩展性特性,非常适合小数据量的字符信息交换。
- 更重要的,XMPP是一个公开的免费的标准,使得不同组织机构的即时消息可以互通,促使IM技术和应用从垄断走向平民化。
----- 但是即时通信的同样也离不开大数据量传输,来解决文件分享,多媒体应用等问题。为了解决这些问题,XEPs中提出了一些办法。在此之前,我们要区分什么是大数量传输,在XMPP\/XEP中,信息传输是所谓字符传输,而数据传输则是字节流传输(bytestreams)。
XEP中对于bytestreams的规定大致如下:
* XEP-0096: File Transfer 这是传输文件的统一接口,客户端之间用它来协商到底采用那种具体的传输方式,包括以下三种。
* XEP-0047: In-Band ByteStreams 带内字节流,这个协议实际上用于小数据量传输,只是它用的字节流传输,所以也顺便说一下。带内,也就是夹带在XML流中,通过XMPP服务器中转传输。具体用法是把数据用base64编码放在XML流中传给对方。这个办法不好,base64编码效率很低,而且所有数据必须由服务器中转。
* XEP-0066: Out of Band Data 带外字节流,带内不行就走带外,也就是不经过XMPP服务器。这个用法是在发起传输的客户端临时建立一个http服务(当然也可以是别的服务),把自己的 IP和端口(通过XMPP消息)告诉接收方,让对方直接来下载。这个方法有一个问题,发送一方必须是公网IP,否则对方无法访问。 注:目前Pandion,Linq支持这个XEP。
* XEP-0065: SOCKS5 Bytestreams SOCKS5字节流,使用SOCKS5传输文件,有直连式和代理传输两种方式。发送方把预定的IP和端口(通过XMPP消息)告诉接收方。如果双方都在公网,采用SOCKS直接传输。如果任何一方在内网,经过SOCKS5代理服务器传输,发送方把代理服务器的IP和端口告诉给接收方。这里的SOCKS5代理服务器和通用的代理服务器稍有差别,因为它需要通过发送方提出的一个sessionID由XMPP服务器通知SOCKS5代理服务器把双方的SOCKS 通道连通,也就是激活。 注:目前Psi,Linq支持这个XEP。
----- google的gtalk宣布采用XMPP标准之后,对于大数据量传输又采用了新的办法,也就是jingle。这个协议除了考虑文件传输,更多的考虑到了多媒体应用,不过总体来说它的思路和前述的方法相差不大,或者说是前述的XEP的扩展和优化。目前jingle在XEP中还处于试验状态,但是在 gtalk中已经采用了jingle,而且gtalk完全不支持前述的XEPs。
大鳄都是这样了,仗着自己有钱有势......。
不过还是要说一下这个jingle,因为google毕竟把jingle公开了,这一点好过某些商业IM服务提供商,至少我们有机会去兼容它。
- XEP-0166: Jingle 这个协议的重点是考虑多媒体应用,当然也包括文件传输,它提出了一些多媒体应用的管理,如字节数据和描述数据分离以及多应用多会话的接口管理方面的建议,对于不同类型的应用,也有相应的jingle补充协议一一描述,如下表:
协议 描述
XEP-0166: Jingle 负责协商和管理所有带外传输的会话
XEP-0167: Jingle Audio via RTP 用RTP传输音频
XEP-0176: Jingle ICE Transport 用ICE传输方法建立和管理数据连接
XEP-0177: Jingle Raw UDP Transport 纯UDP传输
XEP-0180: Jingle Video via RTP 用RTP传输视频
XEP-0181: Jingle DTMF 对DTMF的简单支持
注1:ICE还是IETF正在开发的协议,尚未定型。
注2:DTMF也就是双音频拨号的电话,这里对DTMF的支持只是从XMPP的角度规定,可以管理类DTMF的会话,这样可以通过电话网关在XMPP客户端和普通电话之间用语音聊天。
这些是应用层面的东西,和这里的话题关系不大,另文再说。现在只说在实际字节传输的处理过程。 jingle的自己传输分为三类:
* 发送方在外网,采用类似oob(XEP-0066: Out of Band Data)的方式传输.
* 发送方在内网,采用STUN服务传输,也就是内网客户端的端口影射服务,把内网的IP和端口影射到STUN的IP和特定端口上,然后把这个外网的IP和端口告诉对方,然后还是采用类似oob(XEP-0066: Out of Band Data)的方式传输。
* 发送方在内网,但是没有可用的STUN服务器,采用relay server来转发,也就是这类似于proxy65(XEP-0065: SOCKS5 Bytestreams)的传输方式。
http://bbs.7boo.com.cn/thread-1940-1-1.html
XMPP协议之Socket5 Bytestream文件传输
SOCK5流协商的建立一部分通过XMPP XML流,一部分通过一个独立的socket
实际的文件传输发生在创建的socket上。
第一步:
[发送端] 发送SI(流协商)包A
A:
<iq type='set' id='gaim8215f9ef' [email=to=]to='test@dd.antkingdom.com/Exodus'[/email]>
<si xmlns='http://jabber.org/protocol/si' id='gaim8215f9f0' profile='http://jabber.org/protocol/si/profile/file-transfer'>
<file xmlns='http://jabber.org/protocol/si/profile/file-transfer' name='backup.txt' size='2043'/>
<feature xmlns='http://jabber.org/protocol/feature-neg'>
<x xmlns='jabber:x:data' type='form'><field var='stream-method' type='list-single'>
<option><value>http://jabber.org/protocol/bytestreams</value></option>
</field>
</x>
</feature>
</si>
</iq>
[接收端] 接收A: 发送SI响应包B
B:
<iq id="gaim8215f9ef" to="[email=jjl@dd.antkingdom.com/Home]jjl@dd.antkingdom.com/Home[/email]" type="result">
<si id="gaim8215f9f0" xmlns="http://jabber.org/protocol/si">
<feature xmlns="http://jabber.org/protocol/feature-neg">
<x type="submit" xmlns="jabber:x:data">
<field var="stream-method"><value>http://jabber.org/protocol/bytestreams</value></field>
</x>
</feature>
</si>
</iq>
第二步:
[发送端] 接收B
创建socket,绑定一个地址,并监听(记下IP与端口号),等待连接
构造出如下的bytestream包C,发送包C
C:
<iq type='set' id='gaim8215f9f1' [email=to=]to='test@dd.antkingdom.com/Exodus'[/email]>
<query xmlns='http://jabber.org/protocol/bytestreams' sid='gaim8215f9f0'>
<streamhost [email=jid=]jid='jjl@dd.antkingdom.com/Home'[/email] host='192.168.100.1' port='6642'/>
</query>
</iq>
[接收端] 接收C:
创建一个socket, connect C包中指定的host与port
开始socket 5协商
socket 5协商完毕,发送bytestream响应包D
D:
<iq [email=from=]from='test@dd.antkingdom.com/Exodus'[/email] type='result' [email=to=]to='jjl@dd.antkingdom.com/Home'[/email] id='gaim8215f9f1'>
<query xmlns='http://jabber.org/protocol/bytestreams' sid='gaim8215f9f0'>
<streamhost-used [email=jid=]jid='jjl@dd.antkingdom.com/Home'/[/email]>
</query>
</iq>
第三步:
[发送端] 接收D
开始文件传输
Socket 5协商过程
一、[接收端]发送5,1,0
二、[发送端]接收到5,1,0,发送5,0
三、[接收端]接收到5,0,发送5,1,0,3+digest长度+0+0
注:digest是通过sessionID, 流发起者,流接收者,通过哈希算法得到的一个字符串
四、[发送端]接收到5,1,0,3+digest长度+0+0,发送5,0,0,3+digest长度+0+0
五、socket 协商完毕,建立了P2P的连接,下面通过这个连接的socket就可以进行文件传输了。
jabber/XMPP文件传输的一些情况
1 jabber/XMPP文件传输的一些情况
大家知道,Jabber/XMPP是一种 XML流技术,解决的问题主要是即时消息和出席信息,XML流技术并不适用于大数据量的传输。
即时通信应用中,消息和出席信息的问题相对是比较简单和容易实现的,XMPP的在这方面的长处在于两点:
- 使用了XML流技术,XML天然的结构化和可扩展性特性,非常适合小数据量的字符信息交换。
- 更重要的,XMPP是一个公开的免费的标准,使得不同组织机构的即时消息可以互通,促使IM技术和应用从垄断走向平民化。
----- 但是即时通信的同样也离不开大数据量传输,来解决文件分享,多媒体应用等问题。为了解决这些问题,XEPs中提出了一些办法。在此之前,我们要区分什么是大数量传输,在XMPP\/XEP中,信息传输是所谓字符传输,而数据传输则是字节流传输(bytestreams)。
XEP中对于bytestreams的规定大致如下:
* XEP-0096: File Transfer 这是传输文件的统一接口,客户端之间用它来协商到底采用那种具体的传输方式,包括以下三种。
* XEP-0047: In-Band ByteStreams 带内字节流,这个协议实际上用于小数据量传输,只是它用的字节流传输,所以也顺便说一下。带内,也就是夹带在XML流中,通过XMPP服务器中转传输。具体用法是把数据用base64编码放在XML流中传给对方。这个办法不好,base64编码效率很低,而且所有数据必须由服务器中转。
* XEP-0066: Out of Band Data 带外字节流,带内不行就走带外,也就是不经过XMPP服务器。这个用法是在发起传输的客户端临时建立一个http服务(当然也可以是别的服务),把自己的 IP和端口(通过XMPP消息)告诉接收方,让对方直接来下载。这个方法有一个问题,发送一方必须是公网IP,否则对方无法访问。 注:目前Pandion,Linq支持这个XEP。
* XEP-0065: SOCKS5 Bytestreams SOCKS5字节流,使用SOCKS5传输文件,有直连式和代理传输两种方式。发送方把预定的IP和端口(通过XMPP消息)告诉接收方。如果双方都在公网,采用SOCKS直接传输。如果任何一方在内网,经过SOCKS5代理服务器传输,发送方把代理服务器的IP和端口告诉给接收方。这里的SOCKS5代理服务器和通用的代理服务器稍有差别,因为它需要通过发送方提出的一个sessionID由XMPP服务器通知SOCKS5代理服务器把双方的SOCKS 通道连通,也就是激活。 注:目前Psi,Linq支持这个XEP。
----- google的gtalk宣布采用XMPP标准之后,对于大数据量传输又采用了新的办法,也就是jingle。这个协议除了考虑文件传输,更多的考虑到了多媒体应用,不过总体来说它的思路和前述的方法相差不大,或者说是前述的XEP的扩展和优化。目前jingle在XEP中还处于试验状态,但是在 gtalk中已经采用了jingle,而且gtalk完全不支持前述的XEPs。
大鳄都是这样了,仗着自己有钱有势......。
不过还是要说一下这个jingle,因为google毕竟把jingle公开了,这一点好过某些商业IM服务提供商,至少我们有机会去兼容它。
- XEP-0166: Jingle 这个协议的重点是考虑多媒体应用,当然也包括文件传输,它提出了一些多媒体应用的管理,如字节数据和描述数据分离以及多应用多会话的接口管理方面的建议,对于不同类型的应用,也有相应的jingle补充协议一一描述,如下表:
协议 描述
XEP-0166: Jingle 负责协商和管理所有带外传输的会话
XEP-0167: Jingle Audio via RTP 用RTP传输音频
XEP-0176: Jingle ICE Transport 用ICE传输方法建立和管理数据连接
XEP-0177: Jingle Raw UDP Transport 纯UDP传输
XEP-0180: Jingle Video via RTP 用RTP传输视频
XEP-0181: Jingle DTMF 对DTMF的简单支持
注1:ICE还是IETF正在开发的协议,尚未定型。
注2:DTMF也就是双音频拨号的电话,这里对DTMF的支持只是从XMPP的角度规定,可以管理类DTMF的会话,这样可以通过电话网关在XMPP客户端和普通电话之间用语音聊天。
这些是应用层面的东西,和这里的话题关系不大,另文再说。现在只说在实际字节传输的处理过程。 jingle的自己传输分为三类:
* 发送方在外网,采用类似oob(XEP-0066: Out of Band Data)的方式传输.
* 发送方在内网,采用STUN服务传输,也就是内网客户端的端口影射服务,把内网的IP和端口影射到STUN的IP和特定端口上,然后把这个外网的IP和端口告诉对方,然后还是采用类似oob(XEP-0066: Out of Band Data)的方式传输。
* 发送方在内网,但是没有可用的STUN服务器,采用relay server来转发,也就是这类似于proxy65(XEP-0065: SOCKS5 Bytestreams)的传输方式。
发表评论
-
Android Push Notification
2012-03-22 16:09 1272http://sourceforge.net/projects ... -
使用 XMPP 构建一个基于 web 的通知工具
2011-03-01 10:32 1575http://www.ibm.com/developerwor ... -
Smack 3.2.0 Beta has been released
2011-02-27 20:10 1351大约2个星期前, Smack发布3.2.0 Beta版. 距离 ... -
Jingle XMPP stanza对应的XML schema
2011-02-25 20:22 2924一个典型的Jingle XMPP stanza: <i ... -
GMail add 'voice and video chat' support
2011-02-18 13:32 1953GMail增加对视频聊天的 ... -
Ident协议
2011-02-08 18:06 3391为何要安装 identd ? 曾听过有人形容 id ... -
[原创]使用Smack库实现Google Talk XMPP Extensions - Gmail Notifications (含完整的实现代码以及例子)
2011-02-07 21:39 2644注意: 这里有本人所写的完整的代码, 所以如果要转载, 请征得 ... -
贴个XMPP logs看看Pidgin是如何传输文件的
2011-02-07 20:40 2638zhangsan给lisi发送01.jpg文件. (20:2 ... -
晕, Pidgin在Windows上不支持Voice&Viedo
2011-02-07 20:03 1597从http://pidgin.im/上下载了最新版本2.7.9 ... -
GTALK的运行参数
2011-02-06 21:51 1857/nomutex 同时打开多个Talk。 /forcestar ... -
Smack Jingle库所用的JSTUN库存在的bug
2011-02-06 19:52 4497运行Smack Jingle demo时(http://fis ... -
Google Talk Call Signaling
2011-02-05 22:53 1414http://code.google.com/intl/zh- ... -
几种XMPP客户端实现Jingle语音聊天的总结
2011-02-05 20:48 30900XMPP客户端除了最基本的发送/接收消息,显示好友列表等功能外 ... -
关于ejabberd在Windows 7无法启动
2011-02-04 22:13 2290用了Openfire作为XMPP Server后,突然想试试e ... -
XMPP Client
2011-02-04 20:58 1540Spark http://www.igniterealtime ... -
XMPP Server
2011-02-04 20:50 1731Openfire http://www.igniterealt ... -
XEP-0065: SOCKS5 Bytestreams
2011-02-04 15:24 2985SOCKS5 Bytestreams ("S ... -
XEP-0047: In-Band Bytestreams
2011-02-04 14:34 2201In-Band Bytestreams (IBB) http: ...
相关推荐
基于Asmack库 xmpp 协议 socket5 文件传输
首先,XMPP协议是基于TCP/IP协议之上的,它定义了一种标准格式来传输数据,特别是针对即时通讯中的消息和状态信息。XMPP的核心组件包括Jabber ID(JID)、Stream、XML Stanzas和Components。JID是XMPP用户的唯一标识...
【标题】"安卓XMPP聊天通讯Socket相关-SocketClient.zip" 涉及的主要知识点是XMPP协议在Android平台上的应用以及使用Socket进行网络通信。XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的即时...
【标题】"安卓XMPP聊天通讯Socket相关-简易微信客户端和服务器源码"涉及的核心技术是XMPP(Extensible Messaging and Presence Protocol)协议,这是一种基于XML的即时通讯协议,广泛应用于移动聊天应用,如Android...
XMPP是一种基于XML的实时通讯协议,常用于即时通讯应用,而Socket则是网络编程中的基础概念,用于创建客户端和服务器端之间的连接。 首先,我们需要理解XMPP的工作原理。XMPP的核心是Jabber协议,它定义了客户端和...
XMPP 协议中文参考指南 XMPP(Extensible Messaging and Presence Protocol)是一种基于 XML 的协议,用于实时交换消息和出席信息。该协议的核心功能定义在 RFC 3920 中,包括 XML 流、TLS 和 SASL 加密、流的根...
在Android环境下,使用XMPP(Extensible Messaging and Presence Protocol)协议进行数据传输是一种常见的实现即时通讯的方法。XMPP是一个基于XML的开放标准,用于实时通信和消息传递,它支持多种功能,包括聊天、...
TLS(传输层安全协议)的使用章节讨论了如何通过TLS增强XMPP通信的安全性,实现加密传输。SASL(简单认证和安全层)的使用章节则介绍了在XMPP中实现用户认证的方法。 资源绑定章节解释了如何将多个资源或设备与单一...
总结来说,"安卓XMPP聊天通讯Socket相关-eclipse版Android环信移动客服SDK"是一个用于实现即时通讯功能的SDK,它利用XMPP协议和Socket通信技术,为开发者提供了构建高效、可靠的聊天应用的平台。虽然提供的SDK可能...
### 基于XMPP协议文件传输的研究与实现 #### 概述 本文研究与实现了一个基于XMPP协议的即时通信系统,特别是针对文件传输功能进行了深入探讨。XMPP(可扩展消息处理协议)是一种基于XML(可扩展标记语言)的开放...
【安卓XMPP聊天通讯Socket相关-仿微信即时聊天xmpp4Android第一期.rar】这个压缩包文件主要包含了一个基于XMPP协议实现的Android即时聊天应用的初步开发资源。XMPP(Extensible Messaging and Presence Protocol)是...
XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的实时通信协议,被广泛应用于即时通讯、在线状态管理和数据交换等领域。这份"XMPP协议中文帮助文档"无疑为那些需要理解和应用XMPP技术的开发者...
### XMPP协议(可扩展消息出席协议):核心知识点解析 #### 一、绪论 **1.1 概览** XMPP(可扩展消息和出席协议)是一种开放式的XML协议,旨在支持接近实时的消息传递、出席信息以及请求-响应服务。该协议的基本...
【标题】中的“安卓XMPP聊天通讯Socket相关-XMPP(Android客户端的实现Tomcat版的Androidpn).rar”提到了XMPP(Extensible Messaging and Presence Protocol)在Android平台上的实现,以及它与Tomcat服务器的结合。...
XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的即时通讯协议,常用于实现聊天和在线状态管理,而Socket则是网络编程中的基础概念,用于在两台机器间建立连接并传输数据。 【描述】:“(少包...
在IT行业中,尤其是在移动开发领域,实时通讯系统是不可或缺的一部分,而XMPP(Extensible Messaging and Presence Protocol)是一种被广泛采用的即时通讯协议。本文将深入探讨如何在Android平台上使用ASmack库来...
XMPP的核心概念是构建在TCP/IP协议之上的XML流,使得数据在客户端和服务器之间双向传输。 在XMPP体系架构中,有三个主要角色:客户端(Client)、服务器(Server)和网关(Gateway)。客户端通过TCP/IP连接到服务器...
3. 配置文件:用于设置XMPP服务器和WebRTC连接参数。 4. 用户界面:使用HTML5构建,展示视频流,提供通话控制按钮,以及可能的数据共享功能。 通过分析和理解这个项目,我们可以深入学习WebRTC的信令流程、媒体流...
XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的实时通信协议,主要用于即时消息和在线状态的传输。这个“xmpp协议demo”很显然是一个演示如何使用XMPP协议的项目,可能包含客户端和服务器端的...