




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
los網(wǎng)絡編程實踐iOS網(wǎng)絡編程實踐--NSStream實現(xiàn)TCPSocketiPhone客戶端客戶端我們使用iPhone應用程序,畫面比較簡單。點擊發(fā)送按鈕,給服務器發(fā)送一些字符串過去。點擊接收按鈕就會從服務器讀取一些字符串,并且顯示在畫面上。有關客戶端應用的UI部分不再介紹了,我們直接看代碼部分,Socket客戶端可以采用CFStream或NSStream實現(xiàn),CFStream實現(xiàn)方式與服務器端基本一樣。為了給讀者介紹更多的知識,本例我們采用NSStream實現(xiàn)。NSStream實現(xiàn)采用Objective-C語言,一些面向對象的類。下面我們看看客戶端視圖控制器ViewController.h#import<CoreFoundation/CoreFoundation.h>#include<sys/socket.h>#include<netinet/in.h>#definePORT9000:頑55"標志0為…@property(nonatomic,retain)NSInputStream*inputStream;@property(nonatomic,retain)NSOutputStream*outputStream;
@property(weak,nonatomic)IBOutletUILabel*message;(IBAction)sendData:(id)sender;(IBAction)receiveData:(id)sender;@end定義屬性inputstream和outputstream,它們輸入流NSInputStream和輸出流NSOutputStream類。它們與服務器CFStream實現(xiàn)中的輸入流CFReadStreamRef和輸出流CFWriteStreamRef對應的。視圖控制器ViewController.m的初始化網(wǎng)絡方法initNetworkCommunication代碼:(void)initNetworkCommunication(CFReadStreamRefreadStream;CFWriteStreamRefwriteStream;CFStreamCreatePairWithSocketToHost(NULL,(CFStringRef)@"03",PORT,&readStream,&writeStream);①_inputStream=(bridge_transferNSInputStream*)readStream;②_outputStream=(bridge_transferNSOutputStream*)writeStream;③[_inputStreamsetDelegate:self];④[_outputStreamsetDelegate:self];⑤[_inputStreamscheduleInRunLoop:[NSRunLoopcurrentRunLoop]
forMode:NSDefaultRunLoopMode];⑥[_outputStreamscheduleInRunLoop:[NSRunLoopcurrentRunLoop]forMode:NSDefaultRunLoopMode];⑦[_inputStreamopen];⑧[_outputStreamopen];⑨}點擊發(fā)送和接收按鈕觸發(fā)的方法如下:/*點擊發(fā)送按鈕*/(IBAction)sendData:(id)sender{flag=0;「'init…—/*點擊接收按鈕*/(IBAction)receiveData:(id)sender{flag=1;5—它們都調用initNetworkCommunication方法,并設置操作標識flag,如果flag為0發(fā)送數(shù)據(jù),flag為1接收數(shù)據(jù)。流的狀態(tài)的變化觸發(fā)很多事件,并回調NSStreamDelegate協(xié)議中定義的方法stream:handleEvent:,其代碼如下:
電I-(void)stream:(NSStream*)theStreamhandleEvent:(NSStreamEvent)streamEvent{NSString*event;switch(streamEvent){caseNSStreamEventNone:event=@"NSStreamEventNone”break;caseNSStreamEventOpenCompleted:event=?"NSStreamEventOpenCompleted”break;caseNSStreamEventHasBytesAvailable:event=@"NSStreamEventHasBytesAvailable”if(flag==1&&theStream==_inputStream){NSMutableData*input=[[NSMutableDataalloc]init];uint8_tbuffer[1024];①intlen;while([_inputStreamhasBytesAvailable])②{len=[_inputStreamread:buffermaxLength:sizeof(buffer)];③if(len>0){[inputappendBytes:bufferlength:len];
NSString*resultstring=[[NSStringalloc]initWithData:inputencoding:NSUTF8StringEncoding];NSLog(@”接收:%@”,resultstring);_message.text=resultstring;}break;caseNSStreamEventHasSpaceAvailable:event=?"NSStreamEventHasSpaceAvailable”;if(flag==0&&theStream==_outputStream){//輸出UInt8buff[]="HelloServer!";④[_outputStreamwrite:buffmaxLength:strlen((constchar*)buff)+1];⑤//關閉輸出流[_outputStreamclose];}break;caseNSStreamEventErrorOccurred:event=@"NSStreamEventErrorOccurred”;[selfclose];⑥break;caseNSStreamEventEndEncountered:
event=@"NSStreamEventEndEncountered”;NSLog(@”Error:%d:%@”,[[theStreamstreamError]code],[[theStreamstreamError]localizedDescription]);break;default:[selfclose];⑦event=@"Unknown”;break;?..M,,在讀取數(shù)據(jù)分支(NSStreamEventHasBytesAvailable)中,代碼第①行為讀取數(shù)據(jù)準備緩沖區(qū),本例中設置的是1024個字節(jié),這個大小會對流的讀取有很多的影響。第②行代碼使用hasBytesAvailable方法判斷是否流有數(shù)據(jù)可以讀,如果有可讀數(shù)據(jù)就進行循環(huán)讀取。第③行代碼使用流的read:maxLength:方法讀取數(shù)據(jù)到緩沖區(qū),第1個參數(shù)是緩沖區(qū)對象buffer,第2個參數(shù)是讀取的緩沖區(qū)的字節(jié)長度。在寫入數(shù)據(jù)分支(NSStreamEventHasSpaceAvailable)中,代碼第④行是要寫入的數(shù)據(jù),第⑤行代碼[_outputStreamwrite:buffmaxLength:strlen((constchar*)buff)+1]是寫如數(shù)據(jù)方法。第⑥和第⑦行代碼[selfclose]調用close方法關閉,close方法代碼如下:-_[outputstreamclose];__—
forMode:NSDefaultRunLoopMode];[_outputStreamsetDelegate:nil];[_inputStreamclose];[_inputStreamremoveFromRunLoop:[NSRunLoopcurrentRunLoop]forMode:NSDefaultRunLoopMode];[_inputStreamsetDelegate:nil];}昭[深入淺出Cocoa]iOS網(wǎng)絡編程之CFNetwork[深入淺出Cocoa]iOS網(wǎng)絡編程之CFNetwork羅朝輝(/kesalin/)本文遵循''署名-非商業(yè)用途-保持一致〃創(chuàng)作公用協(xié)議一,CFNetwork簡介首先來回顧下。在前文《[深入淺出Cocoa]iOS網(wǎng)絡編程之Socket》中,提到iOS網(wǎng)絡編程層次模型分為三層:Cocoa層:NSURL,Bonjour,GameKit,WebKitCoreFoundation層:基于C的CFNetwork和CFNetServicesOS層.■基于C的BSDsocket前文講的是最底層的socket,本文將介紹位于CoreFoundation中的CFNetwork。CFNetwork只是對BSDsocket的進行了輕量級的封裝,但在iOS中使用CFNetwork有一個顯著的好處,那就是CFNetwork與系統(tǒng)級別的設置(如:天線設置)以及run-loop結合得很好。每一個線程都有自己的run-loop,因此我們可以CFNetwork當中事件源加入到run-loop中,這樣就可以在線程的run-loop中處理網(wǎng)絡事件了。BTW,大名鼎鼎的ASIHttpRequest庫就是基于CFNetwork封裝的。
本文示例代碼就是這樣做的,源碼請查看:/kesalin/iOSSnippet/tree/master/KSNetworkDemo二,CFNetworkAPI簡介CFNetwork接口是基于C的,下面的接口用于創(chuàng)建一對socketstream,一個用于讀取,一個用于寫入:voidCFStreamCreatePairWithSocketToHost(CFAllocatorRefalloc,CFStringRefhost,UInt32port,CFReadStreamRef*readStream,CFWriteStreamRef*writeStream);該函數(shù)使用host以及port,CFNetwork會將該host轉換為IP地址,并轉換為網(wǎng)絡字節(jié)順序。如果我們只需要一個socketstream,我們可以將另外一個設置為NULL。還有另外兩個''重載”的創(chuàng)建socketsream的接口:CFStreamCreatePairWithSocket和CFStreamCreatePairWithPeerSocketSignature,在這里就不一一介紹了。注意:這些socketstream在使用之前就如原生socket一樣,必須顯式地調用其open函數(shù):BooleanCFReadStreamOpen(CFReadStreamRefstream);BooleanCFWriteStreamOpen(CFWriteStreamRefstream);但與socket不同的是,這兩個接口是異步的,當成功open之后,如果調用方設置了獲取kCFStreamEventOpenCompleted事件的標志的話就會其調用回調函數(shù)。而該回調函數(shù)及其參數(shù)設置是通過如下接口進行的:BooleanCFReadStreamSetClient(CFReadStreamRefstream,CFOptionFlagsstreamEvents,CFReadStreamClientCallBackclientCB,CFStreamClientContext*clientContext);BooleanCFWriteStreamSetClient(CFWriteStreamRefstream,CFOptionFlagsstreamEvents,CFWriteStreamClientCallBackclientCB,CFStreamClientContext*clientContext);該函數(shù)用于設置回調函數(shù)及相關參數(shù)。通過streamEvents標志來設置我們對哪些事件感
興趣;clientCB是一個回調函數(shù),當事件標志對應的事件發(fā)生時,該回調函數(shù)就會被調用;clientcontext是用于傳遞參數(shù)到回調函數(shù)中去。當設置好回調函數(shù)之后,我們可以將socketstream當做事件源調度到run-loop中去,這樣run-loop就能分發(fā)該socketstream的網(wǎng)絡事件了。voidCFReadStreamScheduleWithRunLoop(CFReadStreamRefstream,CFRunLoopRefrunLoop,CFStringRefrunLoopMode);voidCFWriteStreamScheduleWithRunLoop(CFWriteStreamRefstream,CFRunLoopRefrunLoop,CFStringRefrunLoopMode);注意,在我們不再關心該socketstream的網(wǎng)絡事件時,記得要調用如下接口將socketstream從run-loop的事件源中移除。voidCFReadStreamUnscheduleFromRunLoop(CFReadStreamRefstream,CFRunLoopRefrunLoop,CFStringRefrunLoopMode);voidCFWriteStreamUnscheduleFromRunLoop(CFWriteStreamRefstream,CFRunLoopRefrunLoop,CFStringRefrunLoopMode);當我們將socketstream的網(wǎng)絡事件調度到run-loop之后,我們就能在回調函數(shù)中相應各種事件,比如kCFStreamEventHasBytesAvailable讀取數(shù)據(jù):BooleanCFReadStreamHasBytesAvailable(CFReadStreamRefstream);CFIndexCFReadStreamRead(CFReadStreamRefstream,UInt8*buffer,CFIndexbufferLength);或kCFStreamEventCanAcceptBytes寫入數(shù)據(jù):BooleanCFWriteStreamCanAcceptBytes(CFWriteStreamRefstream);CFIndexCFWriteStreamWrite(CFWriteStreamRefstream,constUInt8*buffer,CFIndexbufferLength);最后,我們調用close方法關閉socketstream:voidCFReadStreamClose(CFReadStreamRefstream);voidCFWriteStreamClose(CFWriteStreamRefstream);
三,客戶端示例代碼與socket演示類似,在這里我只演示客戶端示例。同樣,我們也在一個后臺線程中啟動網(wǎng)絡操作:NSURL*url=[NSURLURLWithString:[NSStringstringWithFormat:@"%@:%@",serverHost,serverPort]];NSThread*backgroundThread=[[NSThreadalloc]initWithTarget:selfselector:@selector(loadDataFromServerWithURL:)object:url];[backgroundThreadstart];然后在loadDataFromServerWithURL中創(chuàng)建socket流,并設置其回調函數(shù),將其加入到run-loop的事件源中,然后啟動之:-(void)loadDataFromServerWithURL:(NSURL*)url(NSString*host=[urlhost];NSIntegerport=[[urlport]integerValue];//Keepareferencetoselftouseforcontrollercallbacks//CFStreamClientContextctx=0,(bridgevoid*)(self),NULL,NULL,NULL};//Getcallbacksforstreamdata,streamend,andanyerrors//CFOptionFlagsregisteredEvents=(kCFStreamEventHasBytesAvailable|kCFStreamEventEndEncountered|kCFStreamEventErrorOccurred);//Createaread-onlysocket//CFReadStreamRefreadStream;CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,(bridgeCFStringRef)host,port,&readStream,NULL);//Schedulethestreamontherunlooptoenablecallbacks
//if(CFReadStreamSetClient(readstream,registeredEvents,socketcallback,&ctx)){CFReadStreamScheduleWithRunLoop(readstream,CFRunLoopGetCurrent(),kCFRunLoopCommonModes);}else{[selnetworkFailedWithErrorMessage:@"Failedtoassigncallbackmethod"];return;}//Openthestreamforreading//if(CFReadStreamOpen(readStream)==NO){[selfnetworkFailedWithErrorMessage@"Failedtoopenreadstream"];return;}CFErrorReferror=CFReadStreamCopyError(readStream);if(error!=NULL){if(CFErrorGetCode(error)!=0){NSStrin*errorInfo=[NSStringstringWithFormat:@"Failedtoconnectstream;error'%@'(code%ld)",(bridgeNSString*)CFErrorGetDomain(error),CFErrorGetCode(error)];[selfnetworkFailedWithErrorMessage:errorInfo];}CFRelease(error);return;}NSLog@"Successfullyconnectedto%@",url);//Startprocessing//CFRunLoopRuxX);}參考前面的接口說明,相信你不難理解上面的代碼。前面唯一沒有提到的接口就
是CFReadStreamCopyError,該接口用于獲取當前的錯誤信息,如果沒有錯誤則返回NULL。CFErrorRefCFReadStreamCopyError(CFReadStreamRefstream);CFErrorRefCFWriteStreamCopyError(CFWriteStreamRefstream);此外,我們還可以調用如下接口獲取socketstream的當前狀態(tài):CFStreamStatusCFReadStreamGetStatus(CFReadStreamRefstream);CFStreamStatusCFWriteStreamGetStatus(CFWriteStreamRefstream);在上面的代碼中,我們設置了當有數(shù)據(jù)可以讀取,流到達結尾處時以及錯誤發(fā)生時調用回調函數(shù)socketcallback:voidsocketCallback(CFReadStreamRefstream,CFStreamEventTypeevent,void*myPtr)(KSCFNetworkViewController*controller=(bridgeKSCFNetworkViewController*)myPtr;switch(event){casekCFStreamEventHasBytesAvailable:{//Readbytesuntiltherearenomore//while(CFReadStreamHasBytesAvailable(stream)){UInt8buffer[kBufferSize];intnumBytesRead=CFReadStreamRead(stream,buffer,kBufferSize);[controllerdidReceiveData:[NSDatadataWithBytes:bufferlength:numBytesRead]];}break;}casekCFStreamEventErrorOccurred:{CFErrorReferro=CFReadStreamCopyError(stream);if(error!=NULL){if(CFErrorGetCode(error)!=0){NSStri*gerrorInfo=[NSStringstringWithFormat:@"Failedwhilereadingstream;error'%@'(code%ld)",(bridge
NSString*)CFErrorGetDomain(error),CFErrorGetCode(error)];[controllernetworkFailedWithErrorMessage:errorInfo];}CFRelease(error);}break;}casekCFStreamEventEndEncountered://Finnishreceiveingdata//[controllerdidFinishReceivingData];//Cleanup//CFReadStreamClo(etream);CFReadStreamUnscheduleFromRunLoop(stream,CFRunLoopGetCurrent(),kCFRunLoopCommonModes);CFRunLoopStop(CFRunLoopGetCurrent());break;default:break;}}電上面的代碼也很好理解,當有數(shù)據(jù)可以讀取時,讀取之,然后更新UI;當流到達結尾處時,關閉流,執(zhí)行清理工作;當錯誤發(fā)送時,報告錯誤信息。四,擴展雖然上面的代碼只演示了如何使用CFNetwork的CFReadStream來讀取數(shù)據(jù),寫入數(shù)據(jù)使用CFWriteStream,其工作流程也是一樣的。在這里就不再介紹了。[深入淺出Cocoa]iOS網(wǎng)絡編程之Socket
[深入淺出Cocoa]iOS網(wǎng)絡編程之Socket羅朝輝(/kesalin/)本文遵循''署名-非商業(yè)用途-保持一致〃創(chuàng)作公用協(xié)議一,iOS網(wǎng)絡編程層次模型在前文《深入淺出Cocoa之Bonjour網(wǎng)絡編程》中我介紹了如何在Mac系統(tǒng)下進行Bonjour編程,在那篇文章中也介紹過Cocoa中網(wǎng)絡編程層次結構分為三層,雖然那篇演示的是Mac系統(tǒng)的例子,其實對iOS系統(tǒng)來說也是一樣的。iOS網(wǎng)絡編程層次結構也分為三層:Cocoa層:NSURL,Bonjour,GameKit,WebKitCoreFoundation層:基于C的CFNetwork和CFNetServicesOS層.■基于C的BSDsocketCocoa層是最上層的基于Objective-C的API,比如URL訪問,NSStream,Bonjour,GameKit等,這是大多數(shù)情況下我們常用的API。Cocoa層是基于CoreFoundation實現(xiàn)的。CoreFoundation層:因為直接使用socket需要更多的編程工作,所以蘋果對OS層的socket進行簡單的封裝以簡化編程任務。該層提供了CFNetwork和CFNetServices,其中CFNetwork又是基于CFStream和CFSocket。OS層:最底層的BSDsocket提供了對網(wǎng)絡編程最大程度的控制,但是編程工作也是最多的。因此,蘋果建議我們使用CoreFoundation及以上層的API進行編程。本文將介紹如何在iOS系統(tǒng)下使用最底層的socket進行編程,這和在window系統(tǒng)下使用C/C++進行socket編程并無多大區(qū)別。本文源碼:/kesalin/iOSSnippet/tree/master/KSNetworkDemo運行效果如下:
二,BSDsocketAPI簡介BSDsocketAPI和winsockAPI接口大體差不多,下面將列出比較常用的API:API接口講解socket創(chuàng)建并初始化socket,返回該socket的文件描述符,如果描述符為intsocket(intaddressFamily,-1表示創(chuàng)建失敗。inttype,close關閉protocol)通常參數(shù)addressFamily是IPv4(AF_INET)或IPv6(AF_INET6)。type表intclose(int示socket的類型,通常是流stream(SOCK_STREAM)或數(shù)據(jù)報文socketFileDescriptor)datagram(SOCK_DGRAM)。protocol參數(shù)通常設置為0,以便讓系統(tǒng)自動為選擇我們合適的協(xié)議,對于streamsocket來說會是TCP協(xié)議
(IPPROTO_TCP),而對于datagram來說會是UDP協(xié)議(IPPROTO_UDP)。intbind(intsocketFileDescriptor,sockaddr*addressToBind,intaddressStructLength)將socket與特定主機地址與端口號綁定,成功綁定返回0,失敗返回-1。成功綁定之后,根據(jù)協(xié)議(TCP/UDP)的不同,我們可以對socket進行不同的操作:UDP:因為UDP是無連接的,綁定之后就可以利用UDPsocket傳送數(shù)據(jù)了。TCP:而TCP是需要建立端到端連接的,為了建立TCP連接服務器必須調用listen(intsocketFileDescriptor,intbacklogSize)來設置服務器的緩沖區(qū)隊列以接收客戶端的連接請求,backlogSize表示客戶端連接請求緩沖區(qū)隊列的大小。當調用listen設置之后,服務器等待客戶端請求,然后調用下面的accept來接受客戶端的連接請求。intaccept(intsocketFileDescriptor,sockaddr*clientAddress,intclientAddressStructLength)接受客戶端連接請求并將客戶端的網(wǎng)絡地址信息保存到clientAddress中。當客戶端連接請求被服務器接受之后,客戶端和服務器之間的鏈路就建立好了,兩者就可以通信了。intconnect(intsocketFileDescriptor,sockaddr*serverAddress,intserverAddressLength)客戶端向特定網(wǎng)絡地址的服務器發(fā)送連接請求,連接成功返回0,失敗返回-1。當服務器建立好之后,客戶端通過調用該接口向服務器發(fā)起建立連接請求。對于UDP來說,該接口是可選的,如果調用了該接口,表明設置了該UDPsocket默認的網(wǎng)絡地址。對TCPsocket來說這就是傳說中三次握手建立連接發(fā)生的地方。注意:該接口調用會阻塞當前線程,直到服務器返回。hostent*gethostbyname(char*hostname)使用DNS查找特定主機名字對應的IP地址。如果找不到對應的IP地址則返回NULL。intsend(intsocketFileDescriptor,char*buffer,intbufferLength,intflags)通過socket發(fā)送數(shù)據(jù),發(fā)送成功返回成功發(fā)送的字節(jié)數(shù),否則返回-1。一旦連接建立好之后,就可以通過send/receive接口發(fā)送或接收數(shù)據(jù)了。注意調用connect設置了默認網(wǎng)絡地址的UDPsocket也可以調用該接口來接收數(shù)據(jù)。intreceive(int從socket中讀取數(shù)據(jù),讀取成功返回成功讀取的字節(jié)數(shù),否則返回-1。
socketFileDescriptor,char*buffer,intbufferLength,intflags)一旦連接建立好之后,就可以通過send/receive接口發(fā)送或接收數(shù)據(jù)了。注意調用connect設置了默認網(wǎng)絡地址的UDPsocket也可以調用該接口來發(fā)送數(shù)據(jù)。intsendto(intsocketFileDescriptor,char*buffer,intbufferLength,intflags,sockaddr*destinationAddress,intdestinationAddressLength)通過UDPsocket發(fā)送數(shù)據(jù)到特定的網(wǎng)絡地址,發(fā)送成功返回成功發(fā)送的字節(jié)數(shù),否則返回-1。由于UDP可以向多個網(wǎng)絡地址發(fā)送數(shù)據(jù),所以可以指定特定網(wǎng)絡地址,以向其發(fā)送數(shù)據(jù)。intrecvfrom(intsocketFileDescriptor,char*buffer,intbufferLength,intflags,sockaddr*fromAddress,int*fromAddressLength)從UDPsocket中讀取數(shù)據(jù),并保存發(fā)送者的網(wǎng)絡地址信息,讀取成功返回成功讀取的字節(jié)數(shù),否則返回-1。由于UDP可以接收來自多個網(wǎng)絡地址的數(shù)據(jù),所以需要提供額外的參數(shù),以保存該數(shù)據(jù)的發(fā)送者身份。三,服務器工作流程有了上面的socketAPI講解,下面來總結一下服務器的工作流程。服務器調用socket(...)創(chuàng)建socket;服務器調用listen(...)設置緩沖區(qū);服務器通過accept(...)接受客戶端請求建立連接;服務器與客戶端建立連接之后,就可以通過send(...)/receive(...)向客戶端發(fā)送或從客戶端接收數(shù)據(jù);服務器調用close關閉socket;由于iOS設備通常是作為客戶端,因此在本文中不會用代碼來演示如何建立一個iOS服務器,但可以參考前文:《深入淺出Cocoa之Bonjour網(wǎng)絡編程》看看如何在Mac系統(tǒng)下建立桌面服務器。四,客戶端工作流程由于iOS設備通常是作為客戶端,下文將演示如何編寫客戶端代碼。先來總結一下客戶端工作流程??蛻舳苏{用socket(...)創(chuàng)建socket;客戶端調用connect(...)向服務器發(fā)起連接請求以建立連接;客戶端與服務器建立連接之后,就可以通過send(...)/receive(...)向客戶端發(fā)送或從客戶端接收數(shù)據(jù);客戶端調用close關閉socket;五,客戶端代碼示例下面的代碼就實現(xiàn)了上面客戶端的工作流程:
-(void)loadDataFromServerWithURL:(NSURL*)url(NSString*host=[urlhost];NSNumber*port=[urlport];//Createsocket//intsocketFileDescriptor=socket(AF_INET,SOCK_STREAM,0);if(-1==socketFileDescriptor){NSLog@"Failedtocreatesocket.");return;}//GetIPaddressfromhost//structhostent*remoteHostEnt=gethostbyname([hostUTF8String]);if(NULL==remoteHostEnt){close(socketFileDescriptor);[selfnetworkFailedWithErrorMessage@"Unabletoresolvethehostnameofthewarehouseserver."];return;}structin_addr*remoteInAddr=(structin_addr*)remoteHostEnt->h_addr_list[0];//Setthesocketparameters//structsockaddr_insocketParameters;socketParameters.sin_family=AF_INET;socketParameters.sin_addr=*remoteInAddr;socketParameters.sin_port=htons([portintValue]);//Connectthesocket//intret=connect(socketFileDescriptor,(structsockaddr*)&socketParameters,sizeof(socketParameters));if(-1==ret){close(socketFileDescriptor);NSStrin*errorInfo=[
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 幼兒園實習老師聘用合同協(xié)議
- 區(qū)域戰(zhàn)略合作框架合同
- 房屋買賣合同補充協(xié)議書
- 企業(yè)短期借款合同協(xié)議
- 裝飾裝修材料供需合同范本
- 廣告公司員工培訓合同范本
- 水資源綜合利用工程合同書
- 道路交通事故雙方和解合同書
- 農業(yè)觀光園土地租賃合同
- 小學生每日教育課件
- 2022年RDA5807m+IIC收音機51單片機C程序上課講義
- 雅馬哈貼片機_修機_調機的經驗之談1
- 全自動咖啡機基本結構及原理教程課件
- 金屬風管支架重量計算表
- 正負零以下基礎施工方案(44頁)
- 簡愛人物形象分析(課堂PPT)
- 義務教育《勞動》課程標準(2022年版)
- 從業(yè)務骨干到管理者(課堂PPT)
- 2018年黑龍江統(tǒng)招專升本公共英語真題
- (完整版)小學生必背古詩300首帶拼音版本
- 英文版驗資報告
評論
0/150
提交評論