建立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)
{
if
(Staging == 1) {
}
// 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
if
(Staging == 1) {
}
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
|