以下轉載自神魂顛倒
[4]
ActionScript3.0 Socket編程(4)
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 ];
processFunc( ); // Invoke the appropriate processing function
下面是壹點與薄記相關的處理程序.在妳的代碼中更新currentState從而確保當前協議的狀態.
前面我們所探討的握手步驟的完整的代碼如下:
復制內容到剪貼板代碼:
package {
import flash.display.Sprite;
import flash.events.ProgressEvent;
import flash.net.Socket;
import flash.utils.ByteArray;
public class SocketExample extends Sprite {
// The state constants to describe the protocol
public const DETERMINE_VERSION:int = 0;
public const RECEIVE_CHALLENGE:int = 1;
public const NORMAL:int = 2;
// Maps a state to a processing function
private var stateMap:Object;
// Keeps track of the current protocol state
private var currentState:int;
private var socket:Socket;
public function SocketExample( ) {
// Initialzes the states map
stateMap = new Object( );
stateMap[ DETERMINE_VERSION ] = readVersion;
stateMap[ RECEIVE_CHALLENGE ] = readChallenge;
stateMap[ NORMAL ] = readNormalProtocol;
// Initialze the current state
currentState = DETERMINE_VERSION;
// Create and connect the socket
socket = new Socket( );
socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
socket.connect( "localhost", 2900 );
}
private function onSocketData( eventrogressEvent ):void {
// Look up the processing function based on the current state
var processFunc:Function = stateMap[ currentState ];
processFunc( );
}
private function readVersion( ):void {
// Step 1 - read the version from the server
var version:int = socket.readInt( );
// Once the version is read, the next state is receiving
// the challenge from the server
currentState = RECEIVE_CHALLENGE;
// Step 2 - write the version back to the server
socket.writeInt( version );
socket.flush( );
}
private function readChallenge( ):void {
// Step 3 - read the 8 byte challenge into a byte array
var bytes:ByteArray = new ByteArray( );
socket.readBytes( bytes, 0, 8 );
// After the challenge is received, the next state is
// the normal protocol operation
currentState = NORMAL;
// Step 4 - write the bytes back to the server
socket.writeBytes( bytes );
socket.flush( );
}
private function readNormalProtocol( ):void {
// Step 5 - process the normal socket messages here now that
// that handshaking process is complete
}
}
}
留言列表