天天看點

建立XML來發送到伺服器。

建立XML來發送到伺服器。

在Unity裡,我沒有找到可以不添加大量排行來做這個的标準函數,是以我建立了下述機制:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

public  string buildXMLRPCRequest(Hashtable FieldArray,string MethodName)

{

string  ReturnString =

""

;

ReturnString    +=        

"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>"

+

"\n"

+

"<simpleRPC version=\"0.9\">"

+

"\n"

+

"<methodCall>"

+

"\n"

+

"<methodName>"

+ MethodName +

"</methodName>"

+

"\n"

+

"<vector type=\"struct\">"

;

ReturnString    +=  buildNode(FieldArray);

ReturnString    += 

"\n</vector>"

+

"\n</methodCall>"

+

"\n</simpleRPC>"

;

return

ReturnString;

}

public  string buildNode(Hashtable FieldArray)

{

string  ReturnList =

""

;

foreach (DictionaryEntry Item

in

FieldArray)    {

string  TypeName    =  

"int"

;

string  NodeType    =  

"scalar"

;

Type myType =   Item.Value.GetType();

string  fieldValue  =  

""

;

if

(myType ==

typeof

(string) ) {

TypeName    =  

"string"

;

fieldValue  =   Item.Value.ToString();

}

if

(myType ==

typeof

(Hashtable) ) {

fieldValue  =   buildNode(Item.Value as Hashtable);

NodeType    =  

"vector"

;

TypeName    =  

"struct"

;

}

if

(myType ==

typeof

(int) ) {

fieldValue  =   Item.Value.ToString();

TypeName    =

"int"

;

}

var

ThisNode    =  

"\n<"

+ NodeType +

" type=\""

+ TypeName +

"\" id=\""

+ Item.Key +

"\">"

+ fieldValue +

"</"

+ NodeType +

">"

;

ReturnList +=   ThisNode;

}

return

ReturnList;

}

buildXMLRPCRequest 是用來建立 XML的。

你想要編碼的字段HashTable可能包括types: int, string 或者 Hashtable的對象。它将傳回精美格式化的(簡單)XML-RPC字元串,準備發送到伺服器。

發送

把XML發送到伺服器,你需要發出帶有設定為text/xml的mine類型post請求。标準C#函數沒有一個能用于Unity的,但是用這種buildXMLRPCRequest邏輯輸出非常有效,它所做的是:

在Unity發送:

我使用這個代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

private     void UnityPostXML(  int Staging,

string WebServer,

string MethodName,

Hashtable   FieldArray)

{

string  WebServiceURL   =  

"http://LIVESERVER/"

;

if

(Staging == 1) {

WebServiceURL       =  

"http://TESTSERVER"

;

}

// Encode the text to a UTF8 byte arrray

string XMLRequest   =   buildXMLRPCRequest(FieldArray,MethodName);

System.Text.Encoding enc = System.Text.Encoding.UTF8;

byte[] myByteArray = enc.GetBytes(XMLRequest);

// Get the Unity WWWForm object (a post version)

var

form =

new

WWWForm();

var

url = WebServiceURL;

//  Add a custom header to the request.

//  Change the content type to xml and set the character set

var

headers = form.headers;

headers[

"Content-Type"

]=

"text/xml;charset=UTF-8"

;

// Post a request to an URL with our rawXMLData and custom headers

var

www =

new

WWW(WebServiceURL, myByteArray, headers);

//  Start a co-routine which will wait until our servers comes back

StartCoroutine(WaitForRequest(www));

}

IEnumerator WaitForRequest(WWW www)

{

yield

return

www;

// check for errors

if

(www.error ==

null

)

{

Debug.Log(

"WWW Ok!: "

+ www.text);

}

else

{

Debug.Log(

"WWW Error: "

+ www.error);

}   

}

• 用UTF8把XML編碼成ByteArray

• 建立一個新的Unity WWWForm

• 建立HashTable, 存儲目前的http标頭,覆寫内容類型為text/xml。

• 發送lot給server

• 建立協程等待答複

不适用Unity發送

我發現使用C#(MonoDevelop)的标準版本)開發library比用Uinty開發一切簡單多了。是以如果想用C#做同樣的邏輯發送,如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

private     string NormalXMLCall(int Staging,

string WebServer,

string MethodName,

Hashtable Fields)

{

//  Figure out who to call

string  WebServiceURL   =  

"http://LIVSERVER"

;

if

(Staging == 1) {

WebServiceURL       =  

"http://TESTSERVER"

;

}

WebServiceURL           +=  WebServer;

//  Build the request

XmlRpcParser    parser  =  

new

XmlRpcParser();

string XMLRequest       = parser.buildXMLRPCRequest(Fields,MethodName);

//  Fire it off

HttpWebRequest httpRequest =(HttpWebRequest)WebRequest.Create(WebServiceURL);

httpRequest.Method =

"POST"

;

//Defining the type of the posted data as XML

httpRequest.ContentType =

"text/xml"

;

// string data = xmlDoc.InnerXml;

byte[] bytedata = Encoding.UTF8.GetBytes(XMLRequest);

// Get the request stream.

Stream requestStream = httpRequest.GetRequestStream();

// Write the data to the request stream.

requestStream.Write(bytedata, 0, bytedata.Length);

requestStream.Close();

//Get Response

HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();

// Get the stream associated with the response.

Stream receiveStream = httpResponse.GetResponseStream ();

// Pipes the stream to a higher level stream reader with the required encoding format.

StreamReader readStream =

new

StreamReader (receiveStream, Encoding.UTF8);

string  ReceivedData    =   readStream.ReadToEnd ();

httpResponse.Close ();

readStream.Close ();

return

ReceivedData;

}

}

從 XML中提取資料

我寫了一個簡單的解析器。用于下述findNode函數的構造函數應給予原始XML資料,以及你想要找到的子節點對象。如果節點可以在最進階别的XML字元串找到,它将傳回該節點的值,如果找不到就null。這個解析器是特定于:簡單的XML-RPC,需要花點時間來解碼編碼的字元,那也很簡單。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

public string findNode(string Xml,string SearchForTag) {

int     NestCounter     =   0;

bool    FoundTag        =  

false

;

int     FoundTagLevel   =   0;

string  ReturnValue     =  

null

;

//  Break it down by "<"

string  []  TagArray    =   Xml.Split(

'<'

);

for

(int i=0;i<TagArray.Length;i++) {

if

(i>175 && i<180) {

int Hello=1;

}

string  ThisLine    =  

"<"

+ TagArray[i];

if

(ThisLine.Length <= 1)                                          

continue

;

if

((ThisLine.Length >= 2) && (ThisLine.Substring(0,2) ==

"<?"

))   

continue

;

if

((ThisLine.Length >= 3) && (ThisLine.Substring(0,3) ==

"<--"

))  

continue

;

//  It can be a vector or a scalar - vectors are full of scalars so we'll

ThisLine                =   ThisLine.Replace(

"  "

,

" "

);

ThisLine                =   ThisLine.Replace(

"</"

,

"</"

);

string  []  FieldArray  =   ThisLine.Split('

');

bool    AddLineToResult =   FoundTag;

//  Nest counter is the level we are operating on. We only check the first

//  Level. When a vector is found we increase the NestCount and we won'

t

//  search for the ID

if

(NestCounter <= 1) {

//  Initial array we are looking on level 1