`
guafei
  • 浏览: 321991 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

CFNetwork Programming Guide

阅读更多
CFNetwork封装了具体的网路实现,可以通过CFxxx等api来简单的实现操作
CFNetwork也是基于core foundation的两个API,CFSocket和CFStream



CFSocket是基于BSD socket的抽象,使用CFSocketCreate、CFSocketCreateWithNative
CFSocketCreateRunLoopSource、CFRunLoopAddSource方法创建CFSocket
CFStream提供两种抽象的Stream类型,一种是CFReadStream,一种是CFWriteStream.

使用CFStream读写流数据跟读取UNIX文件类似,首先指定stream的类型(内存、文件、socket等)
然后打开流,进行读写操作。避免主线程阻塞,使用异步方法来读取流。
CFStream支持SSL加密,通过设置kCFStreamPropertySSLSettings属性来设置。



CFNetwork有几种API组成,每种指定着一种网络协议。每种协议的API定义都是类似的
CFFTP API:
1:从ftp服务器中下载文件
2:上传文件到ftp服务器
3:在ftp服务器上创建文件
4:Download a directory listing from an FTP server

CFHTTP API:

CFHTTPAuthentication API支持四种认证方案:
Basic
Digest
NT LAN Manager (NTLM)
Simple and Protected GSS-API Negotiation Mechanism (SPNEGO)

CFHost API处理步骤:
1:创建一个CFHost对象
2:解析CFHost对象
3:获取地址、host名称等信息
4:销毁CFHost对象

CFNetServices API(使用Bonjour服务需要CFNetServices API)

CFNetDiagnostics API(当网络有问题的时候,可以通过这个API来快速定位问题)

//流的读操作
//创建一个读的流:
CFReadStreamRef myReadStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
fileURL);
//打开一个读的流
if (!CFReadStreamOpen(myReadStream)) {
CFStreamError myErr = CFReadStreamGetError(myReadStream);
// An error has occurred.
if (myErr.domain == kCFStreamErrorDomainPOSIX) {
// Interpret myErr.error as a UNIX errno.
} else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) {
// Interpret myErr.error as a MacOS error code.
OSStatus macError = (OSStatus)myErr.error;
// Check other error domains.
}
}
//从流中读取数据
CFIndex numBytesRead;
do {
UInt8 buf[myReadBufferSize]; // define myReadBufferSize as desired
numBytesRead = CFReadStreamRead(myReadStream, buf, sizeof(buf));
if( numBytesRead > 0 ) {
handleBytes(buf, numBytesRead);
} else if( numBytesRead < 0 ) {
CFStreamError error = CFReadStreamGetError(myReadStream);
reportError(error);
}
} while( numBytesRead > 0 );
//关闭流
CFReadStreamClose(myReadStream);
CFRelease(myReadStream);
myReadStream = NULL;


//流的写操作
CFWriteStreamRef myWriteStream =
CFWriteStreamCreateWithFile(kCFAllocatorDefault, fileURL);
if (!CFWriteStreamOpen(myWriteStream)) {
CFStreamError myErr = CFWriteStreamGetError(myWriteStream);
// An error has occurred.
if (myErr.domain == kCFStreamErrorDomainPOSIX) {
// Interpret myErr.error as a UNIX errno.
} else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) {
// Interpret myErr.error as a MacOS error code.
OSStatus macError = (OSStatus)myErr.error;
// Check other error domains.
}
}
UInt8 buf[] = "Hello, world";
CFIndex bufLen = (CFIndex)strlen(buf);
while (!done) {
CFIndex bytesWritten = CFWriteStreamWrite(myWriteStream, buf, (CFIndex)bufLen);
if (bytesWritten < 0) {
CFStreamError error = CFWriteStreamGetError(myWriteStream);
reportError(error);
} else if (bytesWritten == 0) {
if (CFWriteStreamGetStatus(myWriteStream) == kCFStreamStatusAtEnd) {
done = TRUE;
}
} else if (bytesWritten != bufLen) {
// Determine how much has been written and adjust the buffer
bufLen = bufLen - bytesWritten;
memmove(buf, buf + bytesWritten, bufLen);
// Figure out what went wrong with the write stream
CFStreamError error = CFWriteStreamGetError(myWriteStream);
reportError(error);
}
}
CFWriteStreamClose(myWriteStream);
CFRelease(myWriteStream);
myWriteStream = NULL;


在数据转化的时候,如果是同步的,那么就有可能会阻塞主线程,有两种方式可以避免:
1:使用run loop(查看Threading Programming Guide):注册run loop的通知方法,然后在对应的事件上发起通知。
2:使用Polling(轮训)

//创建一个socket,读流
CFStreamCreatePairWithSocketToCFHost(kCFAllocatorDefault, host, port,
&myReadStream, NULL);
//创建一个容器,主要为了回调方法用
CFStreamClientContext myContext = {0, myPtr, myRetain, myRelease, myCopyDesc};
//创建run loop
CFOptionFlags registeredEvents = kCFStreamEventHasBytesAvailable |
kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
if (CFReadStreamSetClient(myReadStream, registeredEvents, myCallBack, &myContext))
{
CFReadStreamScheduleWithRunLoop(myReadStream, CFRunLoopGetCurrent(),
kCFRunLoopCommonModes);
}
//创建一个非阻塞的读流
if (!CFReadStreamOpen(myReadStream)) {
CFStreamError myErr = CFReadStreamGetError(myReadStream);
if (myErr.error != 0) {
// An error has occurred.
if (myErr.domain == kCFStreamErrorDomainPOSIX) {
// Interpret myErr.error as a UNIX errno.
strerror(myErr.error);
} else if (myErr.domain == kCFStreamErrorDomainMacOSStatus) {
OSStatus macError = (OSStatus)myErr.error;
}
// Check other domains.
} else
// start the run loop
CFRunLoopRun();
}

//网络请求回调方法
void myCallBack (CFReadStreamRef stream, CFStreamEventType event, void *myPtr) {
switch(event) {
case kCFStreamEventHasBytesAvailable:
// It is safe to call CFReadStreamRead; it won’t block because bytes
// are available.
UInt8 buf[BUFSIZE];
CFIndex bytesRead = CFReadStreamRead(stream, buf, BUFSIZE);
if (bytesRead > 0) {
handleBytes(buf, bytesRead);
}
// It is safe to ignore a value of bytesRead that is less than or
// equal to zero because these cases will generate other events.
break;
case kCFStreamEventErrorOccurred:
CFStreamError error = CFReadStreamGetError(stream);
reportError(error);
CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(),
kCFRunLoopCommonModes);
CFReadStreamClose(stream);
CFRelease(stream);
break;
case kCFStreamEventEndEncountered:
reportCompletion();
CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(),
kCFRunLoopCommonModes);
CFReadStreamClose(stream);
CFRelease(stream);
break;
}
}


//一般情况下,不建议使用轮训来处理读写流的操作
//轮训一个读流
while (!done) {
if (CFReadStreamHasBytesAvailable(myReadStream)) {
UInt8 buf[BUFSIZE];
CFIndex bytesRead = CFReadStreamRead(myReadStream, buf, BUFSIZE);
if (bytesRead < 0) {
CFStreamError error = CFReadStreamGetError(myReadStream);
reportError(error);
} else if (bytesRead == 0) {
if (CFReadStreamGetStatus(myReadStream) == kCFStreamStatusAtEnd) {
done = TRUE;
}
} else {
handleBytes(buf, bytesRead);
}
} else {
// ...do something else while you wait...
}
}

//轮训一个写的流
UInt8 buf[] = "Hello, world";
UInt32 bufLen = strlen(buf);
while (!done) {
if (CFWriteStreamCanAcceptBytes(myWriteStream)) {
int bytesWritten = CFWriteStreamWrite(myWriteStream, buf, strlen(buf));
if (bytesWritten < 0) {
CFStreamError error = CFWriteStreamGetError(myWriteStream);
reportError(error);
} else if (bytesWritten == 0) {
if (CFWriteStreamGetStatus(myWriteStream) == kCFStreamStatusAtEnd)
{
done = TRUE;
}
} else if (bytesWritten != strlen(buf)) {
// Determine how much has been written and adjust the buffer
bufLen = bufLen - bytesWritten;
memmove(buf, buf + bytesWritten, bufLen);
// Figure out what went wrong with the write stream
CFStreamError error = CFWriteStreamGetError(myWriteStream);
reportError(error);
}
} else {
// ...do something else while you wait...
}
}


http请求
//创建一个http request请求
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,CFDataRef bodyDataExt = CFStringCreateExternalRepresentation(kCFAllocatorDefault,
bodyData, kCFStringEncodingUTF8, 0);
CFHTTPMessageSetBody(myRequest, bodyDataExt);
CFHTTPMessageSetHeaderFieldValue(myRequest, headerFieldName, headerFieldValue);
CFDataRef mySerializedRequest = CFHTTPMessageCopySerializedMessage(myRequest);

//release请求
CFRelease(myRequest);
CFRelease(myURL);
CFRelease(url);
CFRelease(mySerializedRequest);
myRequest = NULL;
mySerializedRequest = NULL;
Communicating with HTTP Servers
Creating a CFHTTP Request
2012-


http相应
//反序列化信息
CFHTTPMessageRef myMessage = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
if (!CFHTTPMessageAppendBytes(myMessage, &data, numBytes)) {
//Handle parsing error
}
//反序列化成功
if (CFHTTPMessageIsHeaderComplete(myMessage)) {
// Perform processing.
}
//反序列化之后可以调用CFHTTPMessageCopyBody等方法获取对应的数据


//通过读的流,序列化一个http请求
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);

//通过CFReadStreamCopyProperty,监听响应
CFHTTPMessageRef myResponse =
(CFHTTPMessageRef)CFReadStreamCopyProperty(myReadStream,
kCFStreamPropertyHTTPResponseHeader);
//返回响应code
UInt32 myErrCode = CFHTTPMessageGetResponseStatusCode(myResponse);
//重定向流
CFReadStreamClose(myReadStream);
CFReadStreamRef myReadStream =
CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest);
if (CFReadStreamSetProperty(myReadStream, kCFStreamPropertyHTTPShouldAutoredirect,
kCFBooleanTrue) == false) {
// something went wrong, exit
}
CFReadStreamOpen(myReadStream);

//关闭流就相当于关闭了这个请求


Authenticating HTTP Servers
如果一个http服务器返回401或者407,那么表示服务端需要认证,请求中需要带上证书,在API中,证书放在CFHTTPAuthentication对象中。



//创建一个authentication对象
if (!authentication) {
CFHTTPMessageRef responseHeader =
(CFHTTPMessageRef) CFReadStreamCopyProperty(
readStream,
kCFStreamPropertyHTTPResponseHeader
);
// Get the authentication information from the response.
authentication = CFHTTPAuthenticationCreateFromResponse(NULL, responseHeader);
CFRelease(responseHeader);
}

//判断这个authentication是否验证
CFStreamError err;
if (!authentication) {
// the newly created authentication object is bad, must return
return;
} else if (!CFHTTPAuthenticationIsValid(authentication, &err)) {// destroy authentication and credentials
if (credentials) {
CFRelease(credentials);
credentials = NULL;
}
CFRelease(authentication);
authentication = NULL;
// check for bad credentials (to be treated separately)
if (err.domain == kCFStreamErrorDomainHTTP &&
(err.error == kCFStreamErrorHTTPAuthenticationBadUserName
|| err.error == kCFStreamErrorHTTPAuthenticationBadPassword))
{
retryAuthorizationFailure(&authentication);
return;
} else {
errorOccurredLoadingImage(err);
}
}
//如果找到证书,那么使用它
else {
cancelLoad();
if (credentials) {
resumeWithCredentials();
}
// are a user name & password needed?
else if (CFHTTPAuthenticationRequiresUserNameAndPassword(authentication))
{
CFStringRef realm = NULL;
CFURLRef url = CFHTTPMessageCopyRequestURL(request);
// check if you need an account domain so you can display it if necessary
if (!CFHTTPAuthenticationRequiresAccountDomain(authentication)) {
realm = CFHTTPAuthenticationCopyRealm(authentication);
}
// ...prompt user for user name (user), password (pass)
// and if necessary domain (domain) to give to the server...
// Guarantee values
if (!user) user = CFSTR("");
if (!pass) pass = CFSTR("");
CFDictionarySetValue(credentials, kCFHTTPAuthenticationUsername, user);
CFDictionarySetValue(credentials, kCFHTTPAuthenticationPassword, pass);
// Is an account domain needed? (used currently for NTLM only)
if (CFHTTPAuthenticationRequiresAccountDomain(authentication)) {
if (!domain) domain = CFSTR("");
CFDictionarySetValue(credentials,kCFHTTPAuthenticationAccountDomain, domain);
}
if (realm) CFRelease(realm);
CFRelease(url);
}
else {
resumeWithCredentials();
}
}
//发起拥有证书的请求
void resumeWithCredentials() {
// Apply whatever credentials we've built up to the old request
if (!CFHTTPMessageApplyCredentialDictionary(request, authentication,
credentials, NULL)) {
errorOccurredLoadingImage();
} else {
// Now that we've updated our request, retry the load
loadRequest();
}
}



把证书放在内存中
//创建一个array来放不同的证书
CFMutableArrayRef authArray;
//创建一个证书的映射
CFMutableDictionaryRef credentialsDict;
//修改映射
CFDictionaryRemoveValue(credentialsDict, authentication);
//寻找一个合适的证书
CFHTTPAuthenticationRef findAuthenticationForRequest {
int i, c = CFArrayGetCount(authArray);
for (i = 0; i < c; i ++) {
CFHTTPAuthenticationRef auth = (CFHTTPAuthenticationRef)
CFArrayGetValueAtIndex(authArray, i);
if (CFHTTPAuthenticationAppliesToRequest(auth, request)) {
return auth;
}
}
return NULL;
}
//获取证书
credentials = CFDictionaryGetValue(credentialsDict, authentication);


持久化证书存储
CFMutableDictionaryRef findCredentialsForAuthentication(
CFHTTPAuthenticationRef auth);
void saveCredentialsForRequest(void);
//如果证书不在缓存中,那么从钥匙串中寻找
didFind =
SecKeychainFindInternetPassword(NULL,
strlen(host), host,
realm ? strlen(realm) : 0, realm,
0, NULL,
path ? strlen(path) : 0, path,
port,
protocolType,
authenticationType,
0, NULL,
&itemRef);

//从钥匙串中加载服务器证书
if (didFind == noErr) {
SecKeychainAttribute attr;
SecKeychainAttributeList attrList;
UInt32 length;
void *outData;
// To set the account name attribute
attr.tag = kSecAccountItemAttr;
attr.length = 0;
attr.data = NULL;
attrList.count = 1;
attrList.attr = &attr;
if (SecKeychainItemCopyContent(itemRef, NULL, &attrList, &length, &outData)
== noErr) {
// attr.data is the account (username) and outdata is the password
CFStringRef username =
CFStringCreateWithBytes(kCFAllocatorDefault, attr.data,
attr.length, kCFStringEncodingUTF8, false);
CFStringRef password =
CFStringCreateWithBytes(kCFAllocatorDefault, outData, length,
kCFStringEncodingUTF8, false);
SecKeychainItemFreeContent(&attrList, outData);
// create credentials dictionary and fill it with the user name & password
credentials =
CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(credentials, kCFHTTPAuthenticationUsername,
username);
CFDictionarySetValue(credentials, kCFHTTPAuthenticationPassword,
password);
CFRelease(username);
CFRelease(password);
}
CFRelease(itemRef);
}

//修改钥匙串的实体
// Set the attribute to the account name
attr.tag = kSecAccountItemAttr;
attr.length = strlen(username);
attr.data = (void*)username;
// Modify the keychain entry
SecKeychainItemModifyContent(itemRef, &attrList, strlen(password),
(void *)password);
//保存钥匙串实体
SecKeychainAddInternetPassword(NULL,strlen(host), host,
realm ? strlen(realm) : 0, realm,
strlen(username), username,
path ? strlen(path) : 0, path,
port,
protocolType,
authenticationType,
strlen(password), password,
&itemRef);



FTP Servers

//流的结构
typedef struct MyStreamInfo {
CFWriteStreamRef writeStream;
CFReadStreamRef readStream;
CFDictionaryRef proxyDict;
SInt64 fileSize;
UInt32 totalBytesWritten;
UInt32 leftOverByteCount;
UInt8 buffer[kMyBufferSize];
} MyStreamInfo;

//从读流中写数据
bytesRead = CFReadStreamRead(info->readStream, info->buffer, kMyBufferSize);
//...make sure bytesRead > 0 ...
bytesWritten = 0;
while (bytesWritten < bytesRead) {
CFIndex result;
result = CFWriteStreamWrite(info->writeStream, info->buffer + bytesWritten,
bytesRead - bytesWritten);
if (result <= 0) {
fprintf(stderr, "CFWriteStreamWrite returned %ld\n", result);
goto exit;
}
bytesWritten += result;
}
info->totalBytesWritten += bytesWritten;

//上传文件
do {
// Check for leftover data
if (info->leftOverByteCount > 0) {
bytesRead = info->leftOverByteCount;
} else {
// Make sure there is no error reading from the file
bytesRead = CFReadStreamRead(info->readStream, info->buffer,
kMyBufferSize);
if (bytesRead < 0) {
fprintf(stderr, "CFReadStreamRead returned %ld\n", bytesRead);
goto exit;
}
totalBytesRead += bytesRead;
}
// Write the data to the write stream
bytesWritten = CFWriteStreamWrite(info->writeStream, info->buffer, bytesRead);
if (bytesWritten > 0) {
info->totalBytesWritten += bytesWritten;
// Store leftover data until kCFStreamEventCanAcceptBytes event occurs
again
if (bytesWritten < bytesRead) {
info->leftOverByteCount = bytesRead - bytesWritten;
memmove(info->buffer, info->buffer + bytesWritten,
info->leftOverByteCount);
} else {
info->leftOverByteCount = 0;
}
} else {
if (bytesWritten < 0)
fprintf(stderr, "CFWriteStreamWrite returned %ld\n", bytesWritten);
break;
}
} while (CFWriteStreamCanAcceptBytes(info->writeStream));



创建一个远程目录

下载目录清单
//从目录清单下载数据
// If previous call had unloaded data
int offset = info->leftOverByteCount;
// Load data from the read stream, accounting for the offset
bytesRead = CFReadStreamRead(info->readStream, info->buffer + offset,
kMyBufferSize - offset);
if (bytesRead < 0) {
fprintf(stderr, "CFReadStreamRead returned %ld\n", bytesRead);
break;
} else if (bytesRead == 0) {
break;
}
bufSize = bytesRead + offset;
totalBytesRead += bufSize;

//下载整个目录并且解析
do
{
bufRemaining = info->buffer + totalBytesConsumed;
bytesConsumed = CFFTPCreateParsedResourceListing(NULL, bufRemaining,
bufSize, &parsedDict);
if (bytesConsumed > 0) {
// Make sure CFFTPCreateParsedResourceListing was able to properly
// parse the incoming data
if (parsedDict != NULL) {
// ...Print out data from parsedDict...
CFRelease(parsedDict);
}
totalBytesConsumed += bytesConsumed;
bufSize -= bytesConsumed;
info->leftOverByteCount = bufSize;
} else if (bytesConsumed == 0) {
// This is just in case. It should never happen due to the large buffer
size
info->leftOverByteCount = bufSize;
totalBytesRead -= info->leftOverByteCount;
memmove(info->buffer, bufRemaining, info->leftOverByteCount);
} else if (bytesConsumed == -1) {
fprintf(stderr, "CFFTPCreateParsedResourceListing parse failure\n");
// ...Break loop and cleanup...
}
} while (bytesConsumed > 0);


使用网络诊断
case kCFStreamEventErrorOccurred:
CFNetDiagnosticRef diagRef =
CFNetDiagnosticCreateWithStreams(NULL, stream, NULL);
(void)CFNetDiagnosticDiagnoseProblemInteractively(diagRef);
CFStreamError error = CFReadStreamGetError(stream);
reportError(error);
CFReadStreamClose(stream);
CFRelease(stream);
break;
  • 大小: 6.2 KB
  • 大小: 7.9 KB
  • 大小: 23.1 KB
  • 大小: 34.8 KB
分享到:
评论

相关推荐

    iphone开发 网络资料 CFNetwork

    CFNetwork Programming Guide详细介绍了iphone网络开发各个方面。从BSD socket 到 CFFTP CFHTTP等等。

    CFNetwork_PG

    CFNetwork Programming Guide is written in English.

    CFNetwork PG

    CFNetwork PG CFNetwork PG

    CFNetwork编程指南

    iOS开发, CFNetwork编程指南,CFNetwork编程指南,CFNetwork编程指南,值得学习 !

    CFNetwork_Framework

    CFNetwork_Framework Reference is written in English.

    iOS CFNetwork编程指南

    CFNetwork+编程指南 详细讲解了iOS CFNetwork编程对于想深入研究CFNetwork框架的同学非常 值得下载学习

    iPhone CFNetwork

    Demo中不仅有连接WebService接口调用,还有WCF服务调用。WCFViewController写了一个例子说明调用过程需传递的参数和返回数据获取。XmlParse文件夹为解析Xml文件,其中两个例子为解析WebService接口返回,一个为WCF...

    CFNetwork.pdf.zip

    CFNetwork.pdf有关IPhone网络开发的电子书

    CFNetwork 编程指南.pdf

    CFNetwork 是核心服务框架中的⼀个框架,它提供了⼀个抽象化的网络协议库。这种抽象使得进行各种网络任务都非常容易,比如: ▪ 使用 BSD sockets ▪ 利用 SSL 或者 TLS 创建加密的连接 ▪ 解析 DNS 主机 ▪ 涉及到 ...

    ios cfnetwork 发送http请求简单实例

    关于ios cfnetwork 发送http请求简单实例

    ASIHTTPRequest 最新版本 包 下载

    使用iOS SDK中的HTTP网络请求API,相当的复杂,调用很繁琐,ASIHTTPRequest就是一个对CFNetwork API进行了封装,并且使用起来非常简单的一套API,用Objective-C编写,可以很好的应用在Mac OS X系统和iOS平台的应用...

    harlogger:简单实用,可将越狱的iOS设备上的解密HTTPHTTPS流量嗅探为HAR格式

    要在越狱设备上触发此功能,您只需为com.apple.CFNetwork放置正确的配置并触发com.apple.CFNetwork.har-capture-update通知即可。 由于此捕获触发了syslog行,这些行可以与它们的产生映像名称和pid关联,因此我们...

    基于CFNetWork的网络请求框架(iOS源代码)

    LHHTTPRequest 是基于CFNetWork的网络请求框架,功能非常强大. LHHTTPRequest 只有两个类: 1.LHHTTPRequest 此类包含了所有的网络请求,一个对象一个请求,GET,POST,下载文件到指定路径,进度追踪,分段下载,断点下载 2....

    iOS的HTTP请求和请求回执类用法小结

    请求类NSURLRequest NSURLRequest类中常用方法和属性总结: //通过类方法创建默认的请求对象 /* 通过这种方式创建的请求对象 默认使用NSURLRequestUseProtocolCachePolicy缓存逻辑 默认请求超时时限为60s ...

    OS X网络程序简单例子

    用CFNETWORK和NSStream写的一个简单通信例子,包括服务端和客户端。 用的xcode。

    OSX服务端+iphone客户端 网络通信小程序

    基于OS X的一个CFNETWORK写的服务端 iphone上的一个客户端,NSStream写的。 实现了基本通信和客户端切到后台后继续保持连接。

    iOS底层网络实现

    iOS网络底层的实现,包括bsd socket ,cfnetwork,nsstream的网络请求实现

    NTP_Component.framework for ios

    使用方法:解压后拷贝framework文件夹到工程目录并添加到工程中,再添加CFNetwork.framework即可使用。 在viewcontroller中调用[[NetworkClock sharedNetworkClock] updateDate]; 并实现GetNTPDateDelegate的-(void)...

    iPhone开发进阶.doc

    • CFNetwork(http,https,ftp,SSL,TLS) • 网络安全 • SQLite(SQL数据库) • XML Core OS • 多线程 • 网络应用(BSD套接字) • 文件系统 • Bonjour(利用无线网络连接其他机器)

Global site tag (gtag.js) - Google Analytics