如果开发个Web端的在线聊天,我们就可以选择直接让客户端与服务器做TCP通信。HTML5中虽然有WebScoket,但是我们也不能一天到晚抱着HTML5不放,毕竟不支持它的浏览器还是大量存在的。所以我们为了支持更多的浏览器使用TCP通信,我们采用了普及率远远高于HTML5的AS。
AS也不是可以随便发送TCP请求的,必须有策略文件的许可才行。AS在向服务器发送TCP请求之前会先发送一个请求让服务器出示策略文件,就像过安检一样= =。。只有策略文件允许当前域访问服务器了,AS才能和服务器建立TCP连接。我们使用AS做HTTP通信的时候,策略文件直接丢在网站更目录下就可以了。但是TCP访问还有一个端口的问题,不能直接从HTTP的策略文件中获得许可。当我们调用socket的connect方法时,AS会向我们请求连接的目标服务器建立一个临时连接,然后发送一个字符(最后包含一个0字符)。这时候,服务器就应该返回策略文件给AS,完成后要关闭这个连接。这个连接是AS的安全策略发起的,不是我们自己发起的连接。这个连接会判断返回的策略文件是否允许连接。下面就是这个策略文件的内容<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="192.168.1.99" to-ports="4435" />
</cross-domain-policy> domain部分是允许访问的域名,后面的to-ports是目标服务器的端口。上面的文件就是允许192.168.1.99这个域上的AS访问服务器的4435端口。AS获得这个文件内容之后就会把我们自己发起的TCP请求发送到服务器上。如果AS没有获取到这个文件,或者获取策略的这次HTTP访问超时,那么AS就会抛出一个2048错误,这个错误就是跨域策略验证失败的错误。这里需要注意的是,服务器在收到策略文件请求之后应该立即发送策略文件,发送成功之后要断开这连接。如果不断开,AS就会认为策略文件的传输还没结束,然后AS等的不耐烦了就会直接断开,并且抛出一个2048错误。(这货脾气好大。。)因为它认为服务器没有断开连接是服务器卡住了,所以它得到了请求超时的结论。
建立连接之后就是数据传输的问题了,由于JavaScript不方便操作字节流,所以我们在Web开发中通常使用纯文本来做TCP传输的数据。AS的socket有提供writeUTF和readUTF两个方法,writeUTF是把字符串写入要发送的数据流中,readUTF是从收到的数据流中读取字符串。这两个方法有一个特点,他们操作的数据,前两个字节是保存发送数据的长度的,从第三个字节开始才是发送的字符串数据。所以如果使用这个两个方法来操作数据在服务器程序开发的时候就需要注意这个格式了。如果你讨厌这样的格式,可以使用write*和read*的其他方法,AS中提供很很多方法,这些方法在AS的手册中就可以找到。最后要注意的是我们把需要发送的文本写入数据流中之后,必须调用flush方法才会发送出去。
现在我把AS写成了JavaScript的接口,由于文件太长了,我就不贴出来了。在文章的最后会提供下载地址,包括AS、HTML和服务器程序的全部源码和编译后的程序。服务器程序是用我最擅长的VB开发的,因为是随手写的,也许还有许多漏洞,所以仅供调试用。如果需要在项目中真正使用这个功能,应该自己开发一个更优秀的服务器程序。下面是我的运行结果的截图。