4.同Socket服务器进行握手,并确定收到了什么样的数据和如何处理这些数据.
创建不同的常量来声明协议的状态.使用这些常量将指定的处理函数映射到相应的状态.在一个socketData事件控制器中,通过状态映射调用这些函数的.
建立Socket连接通常要处理握手这个环节.尤其是在服务器初始化需要向客户端发送数据.然后客户端通过一种特殊的方式相应这些数据,接着服务器因此再次响应.整个处理过程直到握手完成并且建立起一个"正常的"连接为止.
处理服务器的不同响应是非难的,主要的原因是socketData事件控制器不能保存上下文的顺序.也就是说,服务器的响应不会告诉你"为什么"响应, 也不告诉你这些响应数据被那个处理程序来处理.要想知道如何处理这些从服务器返回的响应不能从响应的本身来获得,尤其在响应变化的时候.或许一个响应返回 了两个字节码,另一个返回了一个整数值还跟了一个双精度浮点数.这样看来让响应本身处理自己是一大难题.
我们通过创建一个状态量来标注不同的上下文,服务器通过这些上下文将数据发送到客户端.与这些状态量都有一个相关联的函数来处理该数据,这样你就可以很轻松的按照当前的协议状态去调用正确的处理函数.
当你要与一个Socket服务器建立连接需要考虑如下几个步骤:
1.当与服务器连接的时候,服务器立刻返回一个标志服务器可以支持的最高协议版本号的整数值.
2.客户端在响应的时候会返回一个实际使用协议的版本号.
3.服务器返回一个8byte的鉴定码.
4.然后客户端将这鉴定码返回到服务器.
5.如果客户端的响应不是服务器端所期望的,或者,就在这个时候该协议变成了一个常规操作模式,于是握手结束.
实际上在第四步可以在鉴定码中包含更多的安全响应.你可以通过发送各种加密方法的密匙来代替逐个发送的鉴定码.这通常使用在客户端向用户索要密码的时候, 然后密码成为了加密过的8byte鉴定码.该加密过的鉴定码接着返回到服务器.如果响应的鉴定码匙服务器所期望的,客户端就知道该密码是正确的,然后同意 建立连接.
实现握手框架,你首先要为处理从服务器返回的不同类型的数据分别创建常量.首先,你要从步骤1确定版本号.然后从步骤3收取鉴定码.最后就是步骤5的常规操作模式.我们可以声明
如下常量:
public const DETERMINE_VERSION:int = 0;
public const RECEIVE_CHALLENGE:int = 1;
public const NORMAL:int = 2;
常量的值并不重要,重要的是这些值要是不同的值,两两之间不能有相同的整数值.
下一个步骤我们就要为不同的数据创建不同处理函数了.创建的这三个函数分别被命名为readVersion( ), readChallenge( ) 和 readNormalProtocol( ). 创建完这三个函数后,我们就必须将这三个函数分别映射到前面不同状态常量,从而分别处理在该状态中收到的数据.代码如下:
stateMap = new Object( );
stateMap[ DETERMINE_VERSION ] = readVersion;
stateMap[ RECEIVE_CHALLENGE ] = readChallenge;
stateMap[ NORMAL ] = readNormalProtocol;
最后一步是编写socketData事件处理控制器,只有通过这样的方式,建立在当前协议状态之上的正确的处理函数才可以被调用.首先需要创建一个 currentState的int变量.然后使用stateMap去查询与currentState相关联的函数,这样处理函数就可以被正确调用了.
var processFunc:Function = stateMap[ currentState ];
1. package {
2. import flash.display.Sprite;
3. import flash.events.ProgressEvent;
4. import flash.net.Socket;
5. import flash.utils.ByteArray;
6. public class SocketExample extends Sprite {
7. // The state constants to describe the protocol
8. public const DETERMINE_VERSION:int = 0;
9. public const RECEIVE_CHALLENGE:int = 1;
10. public const NORMAL:int = 2;
11.
12. // Maps a state to a processing function
13. private var stateMap:Object;
14.
15. // Keeps track of the current protocol state
16. private var currentState:int;
17.
18. private var socket:Socket;
19. public function SocketExample( ) {
20. // Initialzes the states map
21. stateMap = new Object( );
22. stateMap[ DETERMINE_VERSION ] = readVersion;
23. stateMap[ RECEIVE_CHALLENGE ] = readChallenge;
24. stateMap[ NORMAL ] = readNormalProtocol;
25.
26. // Initialze the current state
27. currentState = DETERMINE_VERSION;
28. // Create and connect the socket
29. socket = new Socket( );
30. socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
31. socket.connect( "localhost", 2900 );
32. }
33.
34. private function onSocketData( eventrogressEvent ):void {
35. // Look up the processing function based on the current state
36. var processFunc:Function = stateMap[ currentState ];
37. processFunc( );
38. }
39.
40. private function readVersion( ):void {
41. // Step 1 - read the version from the server
42. var version:int = socket.readInt( );
43.
44. // Once the version is read, the next state is receiving
45. // the challenge from the server
46. currentState = RECEIVE_CHALLENGE;
47.
48. // Step 2 - write the version back to the server
49. socket.writeInt( version );
50. socket.flush( );
51. }
52.
53. private function readChallenge( ):void {
54. // Step 3 - read the 8 byte challenge into a byte array
55. var bytes:ByteArray = new ByteArray( );
56. socket.readBytes( bytes, 0, 8 );
57.
58. // After the challenge is received, the next state is
59. // the normal protocol operation
60. currentState = NORMAL;
61.
62. // Step 4 - write the bytes back to the server
63. socket.writeBytes( bytes );
64. socket.flush( );
65. }
66.
67. private function readNormalProtocol( ):void {
68. // Step 5 - process the normal socket messages here now that
69. // that handshaking process is complete
70. }
71. }
72. }
复制代码
processFunc( ); // Invoke the appropriate processing function
下面是一点与薄记相关的处理程序.在你的代码中更新currentState从而确保当前协议的状态.
前面我们所探讨的握手步骤的完整的代码如下:
|