码迷,mamicode.com
首页 > 移动开发 > 详细

ios Communicating with HTTP Servers 与HTTP服务器通信 官方文档翻译(五)

时间:2015-08-30 19:36:11      阅读:657      评论:0      收藏:0      [点我收藏+]

标签:ios   ios开发   iphone   http服务器   通信   



原文地址:developer


时间过的很快,一眨眼周末就过了。人的一生到底怎么样才能过的有意义呢?我一直在找答案。做自己喜欢的事情,爱自己喜欢的人,或是成就一番伟业。都是不错的选择,找到自己想要做的事情,不要放弃寻找。最终生命带走的只能是珍贵的回忆,晚上快乐。


HTTP服务器通信


本章解释了如何创建、发送和接收HTTP请求和响应。



创建一个CFHTTP请求



组成一个HTTP请求消息的远程服务器执行的方法,对象操作(URL),消息头和消息体。方法通常是下列之一:GET, HEAD, PUT, POST, DELETE, TRACE, CONNECT or OPTIONS。创建一个HTTP请求与CFHTTP需要四个步骤:



1.使用CFHTTPMessageCreateRequest函数生成一个CFHTTP消息对象。

2.使用函数CFHTTPMessageSetBody设置消息的主体。

3.设置消息的标题使用CFHTTPMessageSetHeaderFieldValue函数。

4.CFHTTPMessageCopySerializedMessage通过调用函数序列化消息。


示例代码看起来就像清单3中的代码。



CFStringRef bodyString = CFSTR(""); // Usually used for POST data

CFDataRef bodyData = CFStringCreateExternalRepresentation(kCFAllocatorDefault,

bodyString, kCFStringEncodingUTF8, 0);


CFStringRef headerFieldName = CFSTR("X-My-Favorite-Field");

CFStringRef headerFieldValue = CFSTR("Dreams");


CFStringRef url = CFSTR("http://www.apple.com");

CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);


CFStringRef requestMethod = CFSTR("GET");

CFHTTPMessageRef myRequest =

CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL,

kCFHTTPVersion1_1);


CFDataRef bodyDataExt = CFStringCreateExternalRepresentation(kCFAllocatorDefault, bodyData, kCFStringEncodingUTF8, 0);

CFHTTPMessageSetBody(myRequest, bodyDataExt);

CFHTTPMessageSetHeaderFieldValue(myRequest, headerFieldName, headerFieldValue);

CFDataRef mySerializedRequest = CFHTTPMessageCopySerializedMessage(myRequest);


这个示例代码,url是通过调用CFURLCreateWithString首先转换成一个CFURL对象。然后用四个参数:CFHTTPMessageCreateRequest叫做kCFAllocatorDefault指定默认的系统内存分配器是用于创建消息引用,requestMethod指定方法,POST方法,myURL指定URL,http://www.apple.com,kCFHTTPVersion1_1指定消息的HTTP版本是1.1



返回的消息对象引用(myRequest)CFHTTPMessageCreateRequest然后送到CFHTTPMessageSetBody随着消息的主体(bodyData)。然后调用CFHTTPMessageSetHeaderFieldValue使用相同的消息对象引用的名字一起头(headerField)和价值(价值)。头参数是CFString对象等内容长度,和值参数是CFString对象如1260。最后,通过调用CFHTTPMessageCopySerializedMessage消息序列化,应该通过写流发送到接收者,在这个例子中http://www.apple.com




注意:请求主体通常省略。主要将使用请求主体是一个POST请求包含POST数据。它也可以用于其他WebDAV等有关HTTP请求类型的扩展。有关更多信息,请参见RFC 2616




当消息不再需要时,释放消息序列化对象和消息。参见清单3的示例代码





CFRelease(myRequest);

CFRelease(myURL);

CFRelease(url);

CFRelease(mySerializedRequest);

myRequest = NULL;

mySerializedRequest = NULL;



创建一个CFHTTP响应




创建一个HTTP响应几乎完全相同的步骤创建一个HTTP请求。唯一的区别是,而不是调用CFHTTPMessageCreateRequest,你调用函数CFHTTPMessageCreateResponse使用相同的参数。





反序列化传入的HTTP请求



反序列化传入的HTTP请求,创建一个空的消息使用CFHTTPMessageCreateEmpty函数,传递真实的isRequest参数指定要创建一个空的请求消息。然后使用函数CFHTTPMessageAppendBytes将传入消息添加到空的请求消息里。CFHTTPMessageAppendBytes反序列化消息并移除任何可能包含的控制信息。




继续这样做,直到函数CFHTTPMessageIsHeaderComplete返回TRUE。如果你不检查CFHTTPMessageIsHeaderComplete返回TRUE,消息可能是不完整的和不可靠的。一个示例使用清单3 - 3中可以看到这两个函数。



CFHTTPMessageRef myMessage = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);

if (!CFHTTPMessageAppendBytes(myMessage, &data, numBytes)) {

//Handle parsing error

}





在这个示例中,数据是附加的数据和numBytes数据的长度。你可能想叫CFHTTPMessageIsHeaderComplete附加消息的验证头就完成了。




if (CFHTTPMessageIsHeaderComplete(myMessage)) {

// Perform processing.

}




反序列化的消息,您现在可以从以下函数提取信息:

1.CFHTTPMessageCopyBody消息正文的一个副本

2.CFHTTPMessageCopyHeaderFieldValue获得特定的header字段值的副本

3.CFHTTPMessageCopyAllHeaderFields拿到一份所有消息的头字段

4.CFHTTPMessageCopyRequestURL的消息副本的URL

5.CFHTTPMessageCopyRequestMethod得到消息的请求方法的副本




当你不再需要信息,就释放,正确的处理它。






反序列化传入的HTTP响应


就像创建一个HTTP请求非常类似于创建一个HTTP响应,反序列化传入HTTP请求也非常类似于反序列化传入的HTTP响应。唯一重要的区别是,当调用CFHTTPMessageCreateEmpty,你必须通过isRequest参数指定要创建的消息是一个响应消息


使用读取流序列化并发送HTTP请求



您可以使用一个CFReadStream对象序列化和发送CFHTTP请求。当你使用CFReadStream CFHTTP请求对象发送,打开流导致消息序列化和发送在一个步骤。使用CFReadStream对象发送CFHTTP请求让我们更加容易的请求的响应,因为响应是可用属性的流。




序列化并发送一个HTTP请求


使用CFReadStream对象序列化并发送一个HTTP请求,首先创建一个CFHTTP请求和设置消息正文和标题中描述创建一个CFHTTP请求。然后创建一个CFReadStream对象通过调用函数CFReadStreamCreateForHTTPRequest和通过请求您刚刚创建的。最后,CFReadStreamOpen打开读取流。



CFReadStreamCreateForHTTPRequest被调用时,它通过CFHTTP复制请求对象。因此,如果有必要,你可以调用CFReadStreamCreateForHTTPRequest后立即释放CFHTTP请求对象。




因为读流与服务器打开一个套接字连接指定的myUrl参数CFHTTP请求创建时,一段时间前必须允许通过流被认为是开放的。打开读取流也让请求序列化和发送。



如何序列化和发送一个HTTP请求可以看清单3 - 4所示。


CFStringRef url = CFSTR("http://www.apple.com");

CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);

CFStringRef requestMethod = CFSTR("GET");


CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault,

requestMethod, myUrl, kCFHTTPVersion1_1);

CFHTTPMessageSetBody(myRequest, bodyData);

CFHTTPMessageSetHeaderFieldValue(myRequest, headerField, value);


CFReadStreamRef myReadStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest);


CFReadStreamOpen(myReadStream);




检查响应


调度的请求run loop之后,你最终会得到一个头完成回调。在这一点上,你可以叫CFReadStreamCopyProperty阅读得到的消息响应流



CFHTTPMessageRef myResponse = (CFHTTPMessageRef)CFReadStreamCopyProperty(myReadStream, kCFStreamPropertyHTTPResponseHeader);


你可以得到完整的状态行CFHTTPMessageCopyResponseStatusLine响应消息通过调用函数:


CFStringRef myStatusLine = CFHTTPMessageCopyResponseStatusLine(myResponse);


或者只是响应消息的状态代码CFHTTPMessageGetResponseStatusCode通过调用函数


UInt32 myErrCode = CFHTTPMessageGetResponseStatusCode(myResponse);



注意:如果您正在使用这个类同步(没有调用run loop),你必须开始阅读消息通过至少一个调用CFReadStreamRead调用CFReadStreamCopyProperty之前。CFReadStreamRead调用直到数据块(或连接失败)是可用的。不要在你的主应用程序线程上做这个。




处理身份验证错误


如果返回的状态码函数CFHTTPMessageGetResponseStatusCode401(远程服务器需要身份验证信息)407(代理服务器需要身份验证),您需要将身份验证信息附加到请求和发送一遍。请阅读 Communicating with Authenticating HTTP Servers 如何处理身份验证。





处理重定向错误


CFReadStreamCreateForHTTPRequest创建一个读流,自动重定向流默认情况下是禁用的。如果统一资源定位符,或者URL,URL发送请求重定向到另一个,发送请求将导致一个错误的状态码300307不等。如果你收到一个重定向错误,你需要关闭流,创建流再次启用自动重定向,并打开流。参见清单3 - 5



CFReadStreamClose(myReadStream);

CFReadStreamRef myReadStream =

CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest);

if (CFReadStreamSetProperty(myReadStream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue) == false) {

// something went wrong, exit

}

CFReadStreamOpen(myReadStream);




你当你创建一个读取流可能想要启用自动重定向。


取消一个未决请求



一旦请求已经发送,它是不可能阻止远程服务器代理。然而,如果你不再关心响应数据,您可以关闭流。


重要:不要从任何线程关闭流,另一个线程正在等待该流的内容。如果你需要能够终止请求时,您应该使用非阻塞I / O防止所述阻塞在处理流。一定要run loop关闭之前删除流。


























版权声明:本文为博主原创文章,未经博主允许不得转载。

ios Communicating with HTTP Servers 与HTTP服务器通信 官方文档翻译(五)

标签:ios   ios开发   iphone   http服务器   通信   

原文地址:http://blog.csdn.net/wq820203420/article/details/48107221

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!