您的位置:首页 > 理论基础 > 计算机网络

宋体、代码-iOS网络编程实践--NSStream实现TCP Socket iPhone客户端-by小雨

2013-04-15 21:10 771 查看
首先声明,我是一个菜鸟。一下文章中出现技术误导情况盖不负责

客户端我们用应iPhone用应程序,画面比较简单。点击发送钮按,给服务器发送一些字符串去过。点击接收钮按就会从服务器读取一些字符串,并且示显在画面上。





有关客户端用应的UI部份不再绍介了,我们直接看代码部份,Socket客户端可以用采CFStream或NSStream实现。为了给读者绍介更多的知识,本例我们用采NSStream实现。NSStream实现用采Objective-C语言,一些面向对象的类。

上面我们看看客户端视图控制器ViewController.h

#import <CoreFoundation/CoreFoundation.h>

#include <sys/socket.h>

#include <netinet/in.h>

#define PORT 9000

@interface ViewController : UIViewController<NSStreamDelegate>

{

int flag ; //操纵志标 0为发送 1为接收

}

@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

定义属性inputStream和outputStream,它们输入流NSInputStream和出输流NSOutputStream类。它们与服务器CFStream实现中的输入流CFReadStreamRef和出输流CFWriteStreamRef对应的。

视图控制器ViewController.m的初始化网络法方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:[NSRunLoop currentRunLoop]

forMode:NSDefaultRunLoopMode]; ⑥

[_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]

forMode:NSDefaultRunLoopMode];  ⑦

[_inputStream open];  ⑧

[_outputStream open];  ⑨

}

点击发送和接收钮按发触的法方如下:

/* 点击发送钮按  */

- (IBAction)sendData:(id)sender {

flag = 0;

[self initNetworkCommunication];

}

/* 点击接收钮按  */

- (IBAction)receiveData:(id)sender {

flag = 1;

[self initNetworkCommunication];

}

它们都调用initNetworkCommunication法方,并置设操纵识标flag,如果flag为0发送数据,flag为1接收数据。

流的状态的变更发触很多事件,并调回NSStreamDelegate协议中定义的法方stream:handleEvent:,其代码如下:

-(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(@”接收:%@”,resultstring);

_message.text = resultstring;

}

break;

case NSStreamEventHasSpaceAvailable:

event = @”NSStreamEventHasSpaceAvailable”;

if (flag ==0 && theStream == _outputStream) {

//出输

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

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

//关闭出输流

[_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];  ⑦

event = @”Unknown”;

break;

}

NSLog(@”event——%@”,event);

}

在读取数据分支(NSStreamEventHasBytesAvailable)中,代码第①为行读取数据预备缓冲区,本例中置设的是1024个字节,这个小大会对流的读取有很多的影响。第②行代码用应hasBytesAvailable法方判断是不是流有数据可以读,如果有可读数据就进行循环读取。第③行代码用应流的read:maxLength:法方读取数据到缓冲区,第1个数参是缓冲区对象buffer,第2个数参是读取的缓冲区的字节长度。

在入写数据分支(NSStreamEventHasSpaceAvailable)中,代码第④行是要入写的数据,第⑤行代码[_outputStream write:buff maxLength: strlen((const char*)buff)+1]是写如数据法方。

第⑥和第⑦行代码[self close]调用close法方关闭,close法方代码如下:

-(void)close

{

[_outputStream close];

[_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]

forMode:NSDefaultRunLoopMode];

[_outputStream setDelegate:nil];

[_inputStream close];

[_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]

forMode:NSDefaultRunLoopMode];

[_inputStream setDelegate:nil];

}

文章结束给大家分享下程序员的一些笑话语录: 问路

有一个驾驶热气球的人发现他迷路了。他降低了飞行的高度,并认出了地面 上的一个人。他继续下降高度并对着那个人大叫,“打扰一下,你能告诉我我 在哪吗?”

下面那个人说:“是的。你在热气球里啊,盘旋在 30 英尺的空中”。

热气球上的人说:“你一定是在 IT 部门做技术工作”。

“没错”,地面上的人说到,“你是怎么知道的?”

“呵呵”,热气球上的人说,“你告诉我的每件事在技术上都是对的,但对都没 有用”。

地面上的人说,“你一定是管理层的人”。

“没错”,热气球上的人说,“可是你是怎么知道的?”

“呵呵”,地面上的那人说到,“你不知道你在哪里,你也不知道你要去哪,你 总希望我能帮你。你现在和我们刚见面时还在原来那个地方,但现在却是我 错了”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: