IOS的socket编程学习笔记

     苹果的Socket编程,常用的是CFNetwork库编程,Socket编程是一个异步的过程,socket的联接方法,不是会等到连接完成后再执行下一行代码,如果你想在一个连接完全执行完之前与一个Socket完全绑定,那么就会容易得到一个意想不到的结果。
     连接一台Socket服务器你需要确定两个信息,一个是Socket服务器的域名或者IP地址,另一个是服务器监听的端口号.在尝试一个新的Socket连接的时候我们最好先添加一个连接事件监听器.
     CFNetwork库编程,其封装好的开源库是 cocoa AsyncSocket库,它在调用读和写方法完成后,会返回通知,并且能自动地进行socket接收和为每个连接启动新的实例,并且简化了一些流程。
代码如下:

1 //客户端
2 #import "AsyncSocket"
3 @interface HelloIphoneViewController:UIViewController{
4 UITextField *textField;
5 AsyncSocket *asyncSocket;
6 }
7 @property(retain,nonatomic)IBOutlet UITextField *textFiled;
8 -(IBAction)buttonPressed:(id)sender;
9 -(IBAction)textFiledDoneEditing:(id)sender;

//这里用port=0是让系统自动随机找一个空闲端口。其他都是基于c风格对系统函数的直接调用。
//从Socket服务器读数据
对于Socket实例,先收到NSData事件后,然后调用如下两个方法一个,如radByte()或者readInt()什么,在事件控制器确定不会去读过去的bytesAvailable,socket是一个异步的过程,那么我们就不能在socekt一连接,就马上去读数据,而是要等到客户端从服务器载入全部的数据在去读取数据,否者在数据可用之前读数据会产生错误,因此,我们可以通过NSData事件广播到Socket实例,这样就可以知道什么时候,可以读取数据。在需要连接的地方使用connectToHost联接服务器,代码如下:

1 asyncSocket=[[AsyncSocket alloc] initWithDelegate:self];
2 NSError *err=nil;
3 if(![asyncSocket connectToHost on:port error:&err]){
4     NSLog(@"Error:%@",err);
5 }
6 NSD

NSData拥有id和length两个属性的数据空间

1 //NSString 转成NSData
2 NSData *xmlData=[@"data" dataUsingEncoding:NSUTF8StringEncoding];
3 //NSData转换成NSString
4 NSData *data;
5 NSString *result=[[NSString alloc] initWithData:data  encoding:NSUTR8StringEncoding];

通过AsyncSocket:writeDate来发送数据

1 -(void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
2 NSData *aData=[@"tes" dataUsingEncoding:NSUTR8StringEncoding];
3 [socke writeData:aData withTimeout -1 tag:1];

通过重载来处理发送的数据

1 -(void)onSocket:(AsyncSocet *)sock didWriteDataWithTag:(long)tag
2 {{
3     NSLog(@"thread(%),onSocket%p didWriteDataWithTag:%d",[[NSThread currentThread] name] ,sock,tag);
4 }

接收Socket数据,在onSocket重载函数

 1 -(void)onSocket:(AsyncSocet *)sock didReadData:(NSData *)data withTag:(long)tag; 

当收到的数据为ASCII编码,你可以通过方法重新构建一个字符串.

1 NSString *aStr=[[NSString alloc] initWithData:data encoding:NSUTR8StringEncoding];
2 NSLog(@"==%@",aStr);
3 [aStr release];
4 TCP连接读取制定长度的数据
5 socket可以读取固定长度的字节 
6 [socket readdataToLength:withTimeout:tag];
7 //============================================

部分方法的解析

 1 -(void)onSocket:(AsyncSocket *)sock willDisconnectError:(NSError *)err 

发生错误,socket关闭,可以在call-back过程调用"unreadData"去取得socket的最后的数据字节,当连接的时候,该委托方法在 onSocket:didAcceptNewSocket: 或者 onSocket:didConnectToHost: 之前调用;

 1 -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket(AsyncSocket *)didAcceptNewSocket; 

当socket由于或没有错误而断开连接,如果你想要在断开连接后release socket,在此方法工作,而在onSocket:willDisconnectWithError 释放则不安全;

 1 -(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket(AsyncSocket *)didAcceptNewSocket 

当产生一个socket去处理连接时调用,此方法会返回 线程上的run-loop 的新的socket和其应处理的委托,
如果省略,则使用[NSRunLoop cunrrentRunLoop];

 1 -(void)onSocket(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 

当一个socket写入一些数据,但还没有完成整个写入时调用,它可以用来更新进度条等东西;

1 -(NSTimeInterval)onSocket(AsyncSocket *)sock shouldTimeoutreadWithTag:(long)tag elapsect(NSTimeInterval)

2 exapsed bytesDone:(NSUInteger)length 

使用读操作已超时但还没完成时调用,此方法允许随意延迟超时,如果返回一个正的时间间隔,
读取的超时将有一定量的扩展,如果不实现这个方法,或会像往常一样返回一个负的时间间隔,elapsed参数是 原超时的总和,加上先前通过这种方法添加的任何补充, length参数是
读操作到目前为止已读取的字节数, 注意,如果返回正数的话,这个方法可能被一个单独的读取多次调用.
当传入的连接被接受,AsyncSocket调用多个委托方法,这些方法按时间:

1、onSocket:didAcceptNewSocket;
2、onSocket:wantsRunLoopForNewSocket;
3、onSocketWillConnect
-(BOOL)acceptOnPort(UInit16)port error:(NSError *)errptr;

告诉socket开始听取和接受指定端口上的连接,当一个连接到来的时候,AsyncSocket实例将调用各种委托方法,socket将听取所有可用的接口(wifi,以太网等)

-(BOOL)connectToHost(NSString *)hostname onPort(UInit16) port error:(NSError *)errPtr;

连接给定的主机和端口,主机hostname可以是域名或者是Ip地址

-(BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError *)errPtr;

连接到一个给定的地址,指定一个sockaddr结构包裹住一个NSData对象,例如,NSData对象从NSNetService的地址方法返回,如果有一个现有的sockaddr结构,可以将它转换到一个NSData对象,像这样:

struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];

立即断开,任何未处理的读或写都将被丢弃

-(void)disconnect()

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。