最近做的Micro Framework 项目中一直有这么一个需求,就是要调用到服务器上的Web Service,而SDK中的所提供的Sample只包含如何调用设备上的Web Service。
在Micro Framework中使用 Socket 调用Web Service
最近做的Micro Framework 项目中一直有这么一个需求,就是要调用到服务器上的Web Service,而SDK中的所提供的Sample只包含如何调用设备上的Web Service。
既然要服务器上的Web Service,很容易就会想到看看PC上的程序是如何实现Web Service调用的?调用Web Service无疑就是Server与Client间的数据传递,而要检测这个过程,一般就会想到使用到抓包工具,而更加直接的则是使用HttpWatch。
首先我在本地建了一个Web Service程序,该程序包含一个方法:
[WebMethod]
public int add(int a, int b)
{
return a + b;
}
点击调式该程序,
点击Invoke按钮后,开始使用Httpwatch开始录制传送的数据(录制时可能需要重新刷新该页面)
左侧数据为客户端发送数据,右侧为服务器返回数据,其内容如下:
发送的数据:
Code
POST /Service1.asmx/add HTTP/1.1
Accept: */*
Referer: http://localhost:51580/Service1.asmx?op=add
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MS-RTC LM 8)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:51580
Content-Length: 7
Connection: Keep-Alive
Cache-Control: no-cache
a=3&b=3
返回的数据:
Code
HTTP/1.1 200 OK
Server: ASP.NET Development Server/9.0.0.0
Date: Mon, 08 Jun 2009 09:38:39 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 80
Connection: Close
<?xml version="1.0" encoding="utf-8"?>
<int xmlns="http://tempuri.org/">6</int>
按照设定的想法将左侧的数据使用Socket发送到服务器端,并接受来自服务器端的数据。
Code
string post="POST /Service1.asmx/add HTTP/1.1\r\nAccept: */*\r\nReferer: http://localhost:51580/Service1.asmx?op=add\r\nAccept-Language: en-us\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MS-RTC LM 8)\r\nContent-Type: application/x-www-form-urlencoded\r\nAccept-Encoding: gzip, deflate\r\nHost: localhost:51580\r\nContent-Length: 7\r\nConnection: Keep-Alive\r\nCache-Control: no-cache\r\n\r\na=3&b=3";
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect("127.0.0.1",51580);
byte[] bytess = Encoding.UTF8.GetBytes(post);
socket.Send(bytess);
byte[] bytes = new byte[1024];
int x=socket.Receive(bytes);
string s = Encoding.GetEncoding("gb2312").GetString(bytes);
果然会返回预期的结果,接下来就可以将接收到的数据读进XmlReader中进行解析了。
根据对返回数据的分析,我们需要读到Content-Length(实际内容长度),即可将真实内容传到XmlReader方法如下:
Code
private XmlReader GetResponseContent(byte[] bytes)
{
string s = new string(Encoding.UTF8.GetChars(bytes));
char[] splite = new char[] { '\r', '\n' };
string[] result = s.Split(splite);
int contentLenght = Convert.ToInt32(result[12].Substring(16));
byte[] contentbytes = new byte[contentLenght];
Array.Copy(bytes, bytes.Length - contentLenght, contentbytes, 0, contentLenght);
Stream stream = new MemoryStream(contentbytes);
XmlReader xmlReader = XmlReader.Create(stream);
return xmlReader;
}
有了如上的整个实现过程,我们很容易看出只要对发送数据的
POST /Service1.asmx/add HTTP/1.1
Referer: http://localhost:51580/Service1.asmx?op=add
Host: localhost:51580
Content-Length: 7
以及内容进行修改,即可调用不同的方法。