IOS network programming practices-NSStream for TCP Socket iPhone Client

Source: Internet
Author: User

The client uses the iPhone application, and the screen is relatively simple. Click the send button to send some strings to the server. Click the receive button to read some strings from the server and display them on the screen.

 


The UI section of the client application is not introduced anymore. Let's look at the code section directly. The Socket Client can adopt CFStream or NSStream. To introduce more knowledge to readers, we use NSStream in this example. NSStream adopts Objective-C language and some object-oriented classes.

Next let's take a look at the client View Controller ViewController. h

[Cpp]
# Import <CoreFoundation/CoreFoundation. h>
 
# Include <sys/socket. h>
 
# Include <netinet/in. h>
 

 
# Define PORT 9000
 

 
@ Interface ViewController: UIViewController <NSStreamDelegate>
 
{
 
Int flag; // The operation flag 0 indicates sending 1 indicates receiving
 
}
 

 
@ Property (nonatomic, retain) NSInputStream * inputStream;
 
@ Property (nonatomic, retain) NSOutputStream * outputStream;
 

 
@ Property (weak, nonatomic) IBOutlet UILabel * message;
 

 
-(IBAction) sendData :( id) sender;
 
-(IBAction) receiveData :( id) sender;
 

 
@ End

# Import <CoreFoundation/CoreFoundation. h>

# Include <sys/socket. h>

# Include <netinet/in. h>

 

# Define PORT 9000

 

@ Interface ViewController: UIViewController <NSStreamDelegate>

{

Int flag; // The operation flag 0 indicates sending 1 indicates receiving

}

 

@ Property (nonatomic, retain) NSInputStream * inputStream;

@ Property (nonatomic, retain) NSOutputStream * outputStream;

 

@ Property (weak, nonatomic) IBOutlet UILabel * message;

 

-(IBAction) sendData :( id) sender;

-(IBAction) receiveData :( id) sender;

 

@ End


Define the attributes inputStream and outputStream. They input the NSInputStream stream and the NSOutputStream class of the output stream. They correspond to the input stream CFReadStreamRef in the CFStream Implementation of the server and the output stream CFWriteStreamRef.

The initialization network method initNetworkCommunication code of ViewController. m is as follows:

[Cpp]
(Void) initNetworkCommunication
 
{
 
CFReadStreamRef readStream;
 
CFWriteStreamRef writeStream;
 
CFStreamCreatePairWithSocketToHost (NULL,
 
(CFStringRef) @ "192.168.1.103", PORT, & readStream, & writeStream); ①
 
_ InputStream = (_ bridge_transfer NSInputStream *) readStream; ②
 
_ OutputStream = (_ bridge_transfer NSOutputStream *) writeStream; ③
 
[_ InputStream setDelegate: self]; ④
 
[_ OutputStream setDelegate: self]; ⑤
 
[_ InputStream scheduleInRunLoop: [nsunloop currentRunLoop]
 
ForMode: NSDefaultRunLoopMode]; ⑥
 
[_ OutputStream scheduleInRunLoop: [nsunloop currentRunLoop]
 
ForMode: NSDefaultRunLoopMode]; 7
 
[_ InputStream open]; inputs
 
[_ OutputStream open]; then
 
}
 
The method for triggering by clicking the send and receive buttons is as follows:
 
/* Click the send button */
 
-(IBAction) sendData :( id) sender {
 
Flag = 0;
 
[Self initNetworkCommunication];
 
}
 
/* Click "receive */
 
-(IBAction) receiveData :( id) sender {
 
Flag = 1;
 
[Self initNetworkCommunication];
 
}

-(Void) initNetworkCommunication

{

CFReadStreamRef readStream;

CFWriteStreamRef writeStream;

CFStreamCreatePairWithSocketToHost (NULL,

(CFStringRef) @ "192.168.1.103", PORT, & readStream, & writeStream); ①

_ InputStream = (_ bridge_transfer NSInputStream *) readStream; ②

_ OutputStream = (_ bridge_transfer NSOutputStream *) writeStream; ③

[_ InputStream setDelegate: self]; ④

[_ OutputStream setDelegate: self]; ⑤

[_ InputStream scheduleInRunLoop: [nsunloop currentRunLoop]

ForMode: NSDefaultRunLoopMode]; ⑥

[_ OutputStream scheduleInRunLoop: [nsunloop currentRunLoop]

ForMode: NSDefaultRunLoopMode]; 7

[_ InputStream open]; inputs

[_ OutputStream open]; then

}

The method for triggering by clicking the send and receive buttons is as follows:

/* Click the send button */

-(IBAction) sendData :( id) sender {

Flag = 0;

[Self initNetworkCommunication];

}

/* Click "receive */

-(IBAction) receiveData :( id) sender {

Flag = 1;

[Self initNetworkCommunication];

}


Both call the initNetworkCommunication method and set the operation identifier flag. If the flag is 0, the flag is 1 to receive data.

Changing the stream status triggers many events and calls back the stream: handleEvent: method defined in NSStreamDelegate. The Code is as follows:

[Cpp]
-(Void) stream :( NSStream *) theStream handleEvent :( NSStreamEvent) streamEvent {
 
NSString * event;
 
Switch (streamEvent ){
 
Case NSStreamEventNone:
 
Event = @ "NSStreamEventNone ";
 
Break;
 
Case NSStreamEventOpenCompleted:
 
Event = @ "NSStreamEventOpenCompleted ";
 
Break;
 
Case NSStreamEventHasBytesAvailable:
 
Event = @ "NSStreamEventHasBytesAvailable ";
 
If (flag = 1 & theStream = _ inputStream ){
 
NSMutableData * input = [NSMutableData alloc] init];
 
Uint8_t buffer [1024]; ①
 
Int len;
 
While ([_ inputStream hasBytesAvailable]) ②
 
{
 
Len = [_ inputStream read: buffer maxLength: sizeof (buffer)]; ③
 
If (len> 0)
 
{
 
[Input appendBytes: buffer length: len];
 
}
 
}
 
NSString * resultstring = [[NSString alloc]
 
InitWithData: input encoding: NSUTF8StringEncoding];
 
NSLog (@ "receive: % @", resultstring );
 
_ Message. text = resultstring;
 
}
 
Break;
 
Case NSStreamEventHasSpaceAvailable:
 
Event = @ "NSStreamEventHasSpaceAvailable ";
 
If (flag = 0 & theStream = _ outputStream ){
 
// Output
 
UInt8 buff [] = "Hello Server !"; ④
 
[_ OutputStream write: buff maxLength: strlen (const char *) buff) + 1]; ⑤
 
// Close the output stream
 
[_ OutputStream close];
 
}
 
Break;
 
Case NSStreamEventErrorOccurred:
 
Event = @ "NSStreamEventErrorOccurred ";
 
[Self close]; ⑥
 
Break;
 
Case NSStreamEventEndEncountered:
 
Event = @ "NSStreamEventEndEncountered ";
 
NSLog (@ "Error: % d: % @", [[theStream streamError] code],
 
[[TheStream streamError] localizedDescription]);
 
Break;
 
Default:
 
[Self close]; 7
 
Event = @ "Unknown ";
 
Break;
 
}
 
NSLog (@ "event -- % @", event );
 
}

-(Void) stream :( NSStream *) theStream handleEvent :( NSStreamEvent) streamEvent {

NSString * event;

Switch (streamEvent ){

Case NSStreamEventNone:

Event = @ "NSStreamEventNone ";

Break;

Case NSStreamEventOpenCompleted:

Event = @ "NSStreamEventOpenCompleted ";

Break;

Case NSStreamEventHasBytesAvailable:

Event = @ "NSStreamEventHasBytesAvailable ";

If (flag = 1 & theStream = _ inputStream ){

NSMutableData * input = [NSMutableData alloc] init];

Uint8_t buffer [1024]; ①

Int len;

While ([_ inputStream hasBytesAvailable]) ②

{

Len = [_ inputStream read: buffer maxLength: sizeof (buffer)]; ③

If (len> 0)

{

[Input appendBytes: buffer length: len];

}

}

NSString * resultstring = [[NSString alloc]

InitWithData: input encoding: NSUTF8StringEncoding];

NSLog (@ "receive: % @", resultstring );

_ Message. text = resultstring;

}

Break;

Case NSStreamEventHasSpaceAvailable:

Event = @ "NSStreamEventHasSpaceAvailable ";

If (flag = 0 & theStream = _ outputStream ){

// Output

UInt8 buff [] = "Hello Server !"; ④

[_ OutputStream write: buff maxLength: strlen (const char *) buff) + 1]; ⑤

// Close the output stream

[_ OutputStream close];

}

Break;

Case NSStreamEventErrorOccurred:

Event = @ "NSStreamEventErrorOccurred ";

[Self close]; ⑥

Break;

Case NSStreamEventEndEncountered:

Event = @ "NSStreamEventEndEncountered ";

NSLog (@ "Error: % d: % @", [[theStream streamError] code],

[[TheStream streamError] localizedDescription]);

Break;

Default:

[Self close]; 7

Event = @ "Unknown ";

Break;

}

NSLog (@ "event -- % @", event );

}


In the NSStreamEventHasBytesAvailable, code ① reads the data preparation buffer. In this example, it is set to 1024 bytes, which affects the stream reading. The Code in line ② uses the hasBytesAvailable method to determine whether the stream has data that can be read. If there is readable data, it reads it cyclically. The Code in line ③ reads data to the buffer using the stream read: maxLength: method. The first parameter is the buffer object buffer, and the second parameter is the byte length of the read buffer.

In the NSStreamEventHasSpaceAvailable, line ④ of the Code is the data to be written. Line ⑤ code [_ outputStream write: buff maxLength: strlen (const char *) buff) + 1] is a data writing method.

Lines 6 and 7 [self close] Call the close method to close the code. The close method code is as follows:

[Cpp]
-(Void) close
 
{
 
[_ OutputStream close];
 
[_ OutputStream removeFromRunLoop: [nsunloop currentRunLoop]
 
ForMode: NSDefaultRunLoopMode];
 
[_ OutputStream setDelegate: nil];
 
[_ InputStream close];
 
[_ InputStream removeFromRunLoop: [nsunloop currentRunLoop]
 
ForMode: NSDefaultRunLoopMode];
 
[_ InputStream setDelegate: nil];
 
}

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.