`
guafei
  • 浏览: 328853 次
  • 性别: 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 编程指南.pdf

    ### CFNetwork 编程指南知识点概览 #### 1. CFNetwork框架简介 - **定义与定位**:CFNetwork框架是苹果操作系统中的一个核心服务框架,主要为开发者提供了一个高度抽象化的网络协议库。该框架简化了多种网络任务的...

    CFNetwork编程指南

    CFNetwork是苹果公司提供的一套网络编程接口,它为iOS和Mac OS X开发者提供了一种方便、高效的方式来处理网络通信。CFNetwork的API基于BSD套接字(sockets)建立,它提供了一个抽象层,从而简化了网络编程过程,并...

    iOS CFNetwork编程指南

    ### iOS CFNetwork编程指南知识点详解 #### CFNetwork框架概述 CFNetwork是苹果公司开发的一个核心服务框架,它为iOS开发者提供了一系列用于网络任务的API,使得处理网络通信变得更加容易和高效。CFNetwork框架...

    CFNetwork_Framework

    CFNetwork_Framework Reference is written in English.

    CFNetwork.pdf.zip

    《CFNetwork.pdf》是针对iPhone网络开发的一本深入解析指南,它主要涵盖了Apple的CFNetwork框架,这是一个强大的网络编程接口,用于iOS和macOS应用程序。本文将详细阐述CFNetwork的关键概念、架构、功能以及如何在...

    iPhone CFNetwork

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

    ios cfnetwork 发送http请求简单实例

    CFNetwork 框架的核心组件是 CFStream,它是一个抽象的流式数据处理器,负责处理网络数据的读取和写入。 发送 HTTP 请求 要发送 HTTP 请求,需要创建一个 CFReadStreamRef 对象,该对象负责读取网络数据。然后,...

    Professional.iOS.Programming

    书中会详细阐述如何使用iOS的CFNetwork框架或第三方库来实现这些功能,同时讨论FTP协议的工作原理和相关的安全问题。 5. **多线程与GCD**: 为了确保用户体验,iOS应用通常需要在后台执行网络操作。本书将介绍...

    Cocoa Programming For Mac OS X 3rd Edition高清中文翻译版(仅十八章,附原码)

    《Cocoa Programming for Mac OS X》是Mac OS X平台下进行Cocoa开发的经典教程,第3版更是深入浅出地介绍了Cocoa框架的各个方面。这个高清中文翻译版虽然只包含了原书的18章,但对于初学者和有一定基础的开发者来说...

    iPhone-Network-Programming.zip_MacOS编程_Objective-C_

    标题中的"IPhone-Network-Programming.zip"表明这是一个关于iPhone应用中网络编程的资源包,主要针对MacOS平台的开发,使用的编程语言是Objective-C。这个压缩包可能包含了一系列教程、代码示例或文档,帮助开发者...

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

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

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

    在本文中,我们将深入探讨如何在OSX服务端与iPhone客户端之间实现网络通信,主要关注CFNETWORK和NSStream这两个关键的iOS及Mac OS X网络编程框架。这些技术使得应用程序能够处理HTTP、FTP、TCP/IP和其他网络协议,...

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

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

    OS X网络程序简单例子

    在OS X系统中进行网络编程,开发者通常会利用苹果提供的Core Foundation框架中的CFNetwork和Foundation框架中的NSStream类。这两个工具提供了丰富的功能,用于构建基于TCP/IP协议的网络应用程序,适用于服务端和...

    IOS应用源码之CFNetworkTest.rar

    本篇文章将围绕"CFNetworkTest"这一源码,深入探讨CFNetwork在实际应用中的运用与实现。 一、CFNetwork框架简介 CFNetwork是Core Foundation框架的一部分,它是Objective-C的C语言接口,同时也支持Swift。...

    iOS底层网络实现

    本文将深入探讨iOS网络底层的实现,主要涉及BSD Socket、CFNetwork和NSStream这三个关键组件。理解并掌握这些技术,对于优化网络性能、处理复杂网络场景以及编写高效、可靠的网络代码至关重要。 首先,我们来看**...

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

    首先,我们来看看NSURLRequest类的关键方法和属性。 1. **创建请求对象**: - `+ (instancetype)requestWithURL:(NSURL *)URL;` 这个类方法可以创建一个默认的请求对象,它会使用`...

Global site tag (gtag.js) - Google Analytics