.NET Compact Framework 中的网络编程
更新:2007 年 11 月
.NET Compact Framework 提供了内置的 XML Web services 支持,还提供以下协议支持和功能:
基于 HTTP 的协议。
NTLM 身份验证。
SOAP 编码的 XML 内容。此支持包括传递 ADO.NET 数据集。
Web 请求和 Web 响应方法,可以发送 HTTP SOAP 消息和接收响应的 SOAP 消息。
SOAP 库和方法,可以将方法调用和任意对象序列化为 XML SOAP 消息或执行相反的过程(反序列化)。
HTTP 请求
以下几项与发送和接收 HTTP 请求有关:
使用模拟器时,不要将 localhost 用作服务器名称。指定承载 Web 服务的开发计算机的计算机名称或 IP 地址。
与设备一样,模拟器也有自己的 IP 地址。使用 localhost 将指示模拟器使用它自己连接到 Web 服务,而不是使用开发环境或其他桌面计算机所承载的 Web 服务。
例如,不要使用:
https://localhost/myWebService/Service1.asmx
指定下面的选项:
http://ComputerName/myWebService/Service1.asmx
当使用 HttpWebRequest 进行 HTTP 请求时,如果没有可用的连接,设备将启动新的网络连接。因此,如果进行 HTTP 请求只是为了确定是否有可用的连接,会导致设备尝试启动连接,如 GPRS 连接。
.NET Compact Framework 不会在 GlobalProxySelection.Select 属性中存储代理信息,但如果您在代码中指定值,它会将此属性用于 HTTP 连接。
要连接到 Internet,可能需要指定本地代理设置。以下代码显示如何为端口 80 设置代理:
System.Net.GlobalProxySelection.Select = new WebProxy("http://myproxy:80");
如果将 AllowWriteStreamBuffering 设置为 false,则数据不会缓存在内存中,而且不支持 Web 服务器发出的任何身份验证请求或重定向。
为了确保操作成功,请指定绝对路径信息。
注意,有关解析相对文件规范的下列 Windows CE 行为:
file://myfile 被解析为 \\myfile。
file:///myfile 被解析为根目录中的 \myfile。
如果当前计算机中安装的网络协议超过 50 个,.NET Framework 方法 Dns.GetHostName 将引发异常,这是一个已知问题。
若要解决此问题,请卸载实际并不需要的网络协议。要实现这个目标,一种方法是使用 Windows 设备管理器移除未使用的网络适配器。另一种方法是卸载已经安装协议的应用程序。
安全的移动通信
主要有两种用于安全移动通信的方法:
HTTP 身份验证
.NET Compact Framework 支持基本身份验证和摘要式身份验证。这些身份验证机制很简单并且人们也熟知它们的安全性和局限性 -- 局限性之一就是 Web 服务受限于 HTTP 绑定。
.NET Compact Framework 2.0 版支持运行 NTLM 或 Kerberos(Windows 集成身份验证)的服务器,而且不需要对现有的基本或摘要式身份验证进行任何代码转换。
自定义安全标头
.NET Compact Framework 当前不支持 Web 服务安全 (WS-Security) 和 Web 服务增强 (WSE)。
此外,不论您使用 HTTP 还是自定义标头进行身份验证,您都可以使用 SSL 来提高安全性。基本身份验证以明文形式传递名称和密码,所以除非是从 SSL 内部运行,否则并不是很安全。不过,在配合 SSL 使用时,基本身份验证大体上是安全的,唯一一个重要问题是会向目标服务器意外泄露凭据。
注意 .NET Compact Framework 不支持使用 X509 证书的客户端身份验证。
内容长度注意事项
当使用 POST 协议发送流式内容的 HTTP Web 请求时,必须指定内容长度。假设 SendChunked 为 false 并且 Method = POST,则应该为 ContentLength 指定一个值。
与 .NET Framework 全功能版不同,.NET Compact Framework 不预缓冲数据以适应内存限制。若要确保进行缓冲处理,请将 SendChunked 设置为 false。
如果未正确获取和关闭内容长度为零的请求流,它将导致 ObjectDisposedException。若要处理内容长度为零的请求,必须显式调用 GetRequestStream 方法,然后对返回的流调用 Close 方法而不调用 Write 方法,如下面的代码示例所示。
private static void ZeroLengthRequest()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
requestUri + "?dummy=true");
request.AllowWriteStreamBuffering = true;
request.Credentials = CredentialCache.DefaultNetworkCredentials;
request.Credentials = netCred;
request.ConnectionGroupName = "mygroup";
request.ContentLength = 0;
request.KeepAlive = true;
request.Method = "POST";
request.ServicePoint.UseNagleAlgorithm = false;
request.Timeout = System.Threading.Timeout.Infinite;
request.UnsafeAuthenticatedConnectionSharing = true;
Stream req = request.GetRequestStream();
req.Close();
using (request.GetResponse())
{
...
}
}
Private Shared Sub ZeroLengthRequest()
Dim request As HttpWebRequest = _
CType(WebRequest.Create(requestUri + "?dummy=true"), _
HttpWebRequest)
request.AllowWriteStreamBuffering = true
request.Credentials = CredentialCache.DefaultNetworkCredentials
request.Credentials = netCred
request.ConnectionGroupName = "mygroup"
request.ContentLength = 0
request.KeepAlive = true
request.Method = "POST"
request.ServicePoint.UseNagleAlgorithm = false
request.Timeout = System.Threading.Timeout.Infinite
request.UnsafeAuthenticatedConnectionSharing = true
Dim req As Stream = request.GetRequestStream
req.Close
request.GetResponse
End Sub