在国庆这段时间里用零星的一些时间看了一下socket的学习资料,由于笔者偏向学习实用方面的内容,因此此篇文章涉及理论知识较少,主要是以实现思路(怎么做)为主,但在实现之前还是需要了解一些基础的理论知识(如果其中有误请指出)
TCP是用socket来实现,或者说socket就是对TCP的封装,因此要想明白Socket连接,先要明白TCP连接。
TCP(传输控制协议)(对应TCP的另一种协议是UDP协议,读者可自行查阅相关资料)
作用:建立连接,形成传输数据的通道
特点:在连接中进行大数据传输(数据大小不收限制)
优点:通过三次握手完成连接,是可靠协议,安全送达(关于三次握手可以用打电话的例子说明)
劣势:必须建立连接,效率会稍低
通过此图可以看出通信的两端都是Socket,因此网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输。
这里不做服务端介绍,主要介绍客户端的实现,以下为实现代码及说明
/** 主要实现思路 * 1.创建主机地址,设置端口号 2.连接到主机 3.将c语言输入输出流转化为oc语言并代理 4.打开输入输出流,并加入消息循环池 最后个根据代理方法来监听输入输出流的变化即可 */ //设置主机地址和端口号根据服务端所给端口号设置 NSString *host = @"127.0.0.1"; int port = 12345; //创建c语言输入输出流 CFReadStreamRef readStream; CFWriteStreamRef writeStream; //链接至主机 CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream); //将c语言输入输出流转化为oc对象,此处用到定义好的OC全局变量 _outputStream = (__bridge NSOutputStream *)writeStream; _inputStream = (__bridge NSInputStream *)readStream; //设置代理 _outputStream.delegate = self; _inputStream.delegate = self; //打开输入输出流通道并监听 [_outputStream open]; [_inputStream open]; //加入消息循环池,若不放入消息循环池不能做到监听 [_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [_inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
接下来实现输入输出流的代理方法让我们可以实时监听输入输出流的改变
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { case NSStreamEventOpenCompleted: // NSLog(@"%@",[aStream class]); NSLog(@"连接到主机完成"); break; case NSStreamEventHasBytesAvailable: // NSLog(@"%@",[aStream class]); NSLog(@"有字节可读"); //读取对应的字节 [self readData]; break; case NSStreamEventHasSpaceAvailable: NSLog(@"%@",[aStream class]); NSLog(@"可发送字节"); break; case NSStreamEventErrorOccurred: NSLog(@"链接错误"); break; case NSStreamEventEndEncountered: NSLog(@"断开链接"); //链接断开后需要关闭输出输出流通道并将其移出消息循环池 [_outputStream close]; [_inputStream close]; [_outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; break; default: break; } }
对应的就有输出数据和输入数据
//输出数据,此处name需要匹配服务器端输入格式要求 NSString *name = [@"iam:" stringByAppendingString:@"lisi"]; //做出对应的转化 NSData *data = [name dataUsingEncoding:NSUTF8StringEncoding]; //将数据输出 [_outputStream write:data.bytes maxLength:data.length]; //有输出后输入端会监听到接收了新的数据此处就可以直接读取 - (void)readData { //设置一个字符数组用于接收字符数据 uint8_t buff[1024]; //获取字符数据并得到其长度 NSUInteger length = [_inputStream read:buff maxLength:sizeof(buff)]; //将接收的字符数组转化为OC对象 NSString *receving = [[NSString alloc] initWithBytes:buff length:length encoding:NSUTF8StringEncoding]; NSLog(@"%@",receving); }
从上述代码中可以看出socket的使用方法其实还是较为简单,关键是需要理解到其实现步骤,只要记住了步骤再做出对应的转化就能很好的实现,当然此处只是最简单的socket编程。希望此文对各位有帮助,最后祝大家国庆快乐!
时间: 2024-12-28 21:42:24