[Cocoa] nsstream for iOS Network Programming

Source: Internet
Author: User
ArticleDirectory
    • Iv. Conclusion

[Cocoa] nsstream for iOS Network Programming

Luo chaohui (http://www.cnblogs.com/kesalin)

This article follows the "signature-non-commercial use-consistency" creation public agreement 1. Introduction to nsstream First, let's review it. In the previous article [Exploring cocoa] socket for iOS network programming, we mentioned that the Layer Model of IOS network programming is divided into three layers:
    • Cocoa layer: nsurl, bonjour, game kit, WebKit
    • Core Foundation layer:C-basedCfnetwork and cfnetservices
    • OS layer: C-based BSD socket
Previous articles: socket for iOS network programming and 《Cfnetwork for iOS Network ProgrammingThis article describes the underlying socket and cfnetwork at the core foundation layer. Nsstream is actually a simple encapsulation of cfnetwork with objective-C, It uses The nsstreamdelegate protocol is used to implement the callback function in the cfnetwork. Similarly, runloop works well with nsstream. Nsstream has two entity classes: nsinputstream and nsoutputstream, which correspond to cfreadstream and cfwritestream in cfnetwork respectively. ExampleCodeSee: Https://github.com/kesalin/iOSSnippet/tree/master/KSNetworkDemo II. Introduction to nsstream APIs

NsstreamClass has the following interfaces:

-(Void) Open;

-(Void) Close;

-(ID<Nsstreamdelegate>) Delegate;

-(Void) Setdelegate :(ID<Nsstreamdelegate>) Delegate;

-(Void) Scheduleinrunloop :(Nsunloop*) Arunloop formode :(Nsstring*) Mode;

-(Void) Removefromrunloop :(Nsunloop*) Arunloop formode :(Nsstring*) Mode;

-(Nsstreamstatus) Streamstatus;

-(Nserror*) Streamerror;

Some nsstream interfaces are similar to cfnetwork interfaces, such as opening, closing, obtaining status and error information, and combining them with runloop. As mentioned above, nsstream implements the callback function in cfnetwork through nsstreamdelegate. This Optional Protocol has only one interface:

-(Void) Stream :(Nsstream*) Astream handleevent :(Nsstreamevent) Eventcode;

Nsstreamevent is a stream event enumeration:

Typedef Ns_options(Nsuinteger, nsstreamevent ){

Nsstreameventnone =0,

Nsstreameventopencompleted =1Ul <0,

Nsstreameventhasbytesavailable =1Ul <1,

Nsstreameventhasspaceavailable =1Ul <2,

Nsstreameventerroroccurred =1Ul <3,

Nsstreameventendencountered =1Ul <4

};

The meanings of these event enumerations are similar to those of cfstreameventtype in cfnetwork, so they are no longer repeated here.

NsinputstreamClass has the following interfaces:

-(Nsinteger) Read :(Uint8_t*) Buffer maxlength :(Nsuinteger) Len;
When data is read from the stream to the buffer, the buffer length should not be less than Len. This interface returns the actual length of data read (the maximum length is Len ).

-(Bool) Getbuffer :(Uint8_t**) Buffer length :(Nsuinteger*) Len;
Obtain the data and size of the current stream. Note that the buffer is valid only before the next stream operation.

-(Bool) Hasbytesavailable;
Check whether there is any data in the stream.

NsoutputstreamClass has the following interfaces:

-(Nsinteger) Write :(Const Uint8_t*) Buffer maxlength :(Nsuinteger) Len;
Writes data in the buffer to the stream, and returns the actual number of bytes written.

-(Bool) Hasspaceavailable;
Check whether there is any space for writing in the stream.

From these interfaces, nsstream is a simple objective-C encapsulation on the cfnetwork. But nsstream in IOS does not support nshost, which is a defect and apple is aware of this problem (http://developer.apple.com/library/ios/#qa/qa1652/_index.html). We can implement this feature through nsstream's extended functions:

 @ Implementation  Nsstream (streamstohost) + ( Void ) Getstreamstohostnamed :( Nsstring * ) HostnamePort:( Nsinteger) PortInputstream:(  Out Nsinputstream **) InputstreamptrOutputstream:(  Out Nsoutputstream ** ) Outputstreamptr {cfreadstreamref readstream; cfwritestreamref writestream; Assert (hostname ! = Nil); Assert (Port > 0 ) & (Port < 65536  ); Assert (inputstreamptr ! = NULL) | (outputstreamptr! = Null); readstream = NULL; writestream =NULL; cfstreamcreatepairwithsockettohost (null, (_ bridge cfstringref) hostname, port, (inputstreamptr ! = NULL )? & Readstream: NULL), (outputstreamptr ! = NULL )? & Writestream: NULL ));  If (Inputstreamptr! = Null ){ * Inputstreamptr = Cfbridgingrelease (readstream );}  If (Outputstreamptr! =Null ){ * Outputstreamptr = Cfbridgingrelease (writestream );}}  @ End 

 

3. Client sample code

Similar to the previous example, here I only demonstrate the client example. Similarly, we also start network operations in a background thread:

Nsurl * url = [nsurl urlwithstring: [nsstring stringwithformat:@"% @: % @", Serverhost, SERVERPORT]; nsthread* Backgroundthread =[[Nsthread alloc] initwithtarget: Self selector: @ selector (loaddatafromserverwithurl :)Object: Url]; [backgroundthread start];

Create an nsinputstream in loaddatafromserverwithurlAnd set its delegate, add it to the event source of Run-loop, then open the stream and run runloop:

-(Void) Loaddatafromserverwithurl :( nsurl *) URL {nsinputstream*Readstream; [nsstream getstreamstohostnamed: [url host] Port: [[url port] integervalue] inputstream:&Readstream outputstream: NULL]; [readstream setdelegate: Self]; [readstream scheduleinrunloop: [nsunloop currentrunloop] formode: Unknown]; [readstream open]; [[nsunloop currentrunloop] Run];}

Because we use ksnsstreamviewcontroller as the delegate of nsinputstream, we need to implement the delgate in ksnsstreamviewcontroller:

 # Pragma Mark nsstreamdelegate -( Void ) Stream :( nsstream *) Stream handleevent :( nsstreamevent) eventcode {nslog (  @"  > Nsstreamdelegate in thread % @  "  , [Nsthread currentthread]);  Switch  (Eventcode ){  Case  Nsstreameventhasbytesavailable :{  If (_ Receiveddata = Nil) {_ receiveddata =[[Nsmutabledata alloc] init];} uint8_t Buf [kbuffersize];  Int Numbytesread = [(Nsinputstream *) stream read: Buf maxlength:Kbuffersize  ];  If (Numbytesread> 0  ) {[Self didreceivedata: [nsdata datawithbytes: Buf length: numbytesread];}  Else   If (Numbytesread = 0 ) {Nslog (  @"  > End of stream reached  "  );}  Else  {Nslog (  @"  > Read error occurred  "  );}  Break  ;}  Case Nsstreameventerroroccurred: {nserror * Error = [Stream streamerror]; Nsstring * Errorinfo = [nsstring stringwithformat: @"  Failed while reading stream; error '% @' (code % d)  "  , Error. localizeddescription, error. Code]; [self cleanupstream: stream]; [self networkfailedwitherrormessage: errorinfo];}  Case  Nsstreameventendencountered: {[self cleanupstream: stream]; [self didfinishreceivingdata]; Break  ;}  Default  :  Break  ;}} 

When Data Reading is complete or reading fails, call the cleanupstream method to close the stream:

 
-(Void) Cleanupstream :( nsstream *) Stream {[stream removefromrunloop: [nsunloop currentrunloop] formode: nsdefaultrunloopmode]; [stream close]; stream=Nil ;}

 

Iv. Conclusion

Through the example above, we can see that nsstream only uses objective-C to encapsulate a simple layer of cfnetwork, but it makes it much easier for us to program using socket, so in most cases, we should give priority to nsstream for socket programming.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.