首页 > 代码库 > Scoket
Scoket
流程:
服务器: 客户端:
监听端口,等待访问 指定服务器ip、端口、传输协议
↓ ↓
请求
←-----------------------------
-----------------------------→
响应并建立连接
↓ ↓
IO传输
<------------------------------>
↓ ↓
关闭socket,释放资源 关闭socket,释放资源
2.Peer To Peer 点对点通信(蓝牙)
服务器端
.h
#import <Foundation/Foundation.h>#import <netinet/in.h>#import <sys/socket.h>@interface Server : NSObject<NSNetServiceDelegate>@property(nonatomic,strong)NSNetService *service;@property(nonatomic,strong)NSSocketPort *socket;@property(nonatomic,strong)NSInputStream *inputStream;@property(nonatomic,strong)NSOutputStream *outputStream;@property(nonatomic,assign)int port;@end
.m
#import "Server.h"/* 服务器接收到客户端请求后回调,它是CFSocketCallBack类型 */void AcceptCallBack(CFSocketRef socket,CFSocketCallBackType type,CFDataRef address,const void *data,void *info);/* 客户端在socket中读取数据时调用 */void WriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType,void *clientCallBackInfo);/* 客户端把数据写入socket时调用 */void ReadStreamClientCallBack(CFReadStreamRef stream,CFStreamEventType eventType, void *clientCallBackInfo);@implementation Server-(id)init{ if (self = [super init]) { if ([self startServer]) { [self publishService]; }else{ NSLog(@"启动服务器失败"); } } return self;}-(BOOL)startServer{ /*定义一个server socket引用*/ CFSocketRef sserver; //创建socket context CFSocketContext ctx = {0,(__bridge void *)(self),NULL,NULL,NULL}; //创建server socket TCP IPv4设置回调函数 sserver = CFSocketCreate(NULL, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)AcceptCallBack, &ctx); if (sserver == NULL) { return NO; } //设置是否重新绑定标志 int yes = 1; //设置socket的属性 SOL_SOCKET设置tcp SO_REUSEADDR是重新绑定 yes 是否重新绑定 setsockopt(CFSocketGetNative(sserver), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); //设置端口和地址 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); //memset函数对指定的地址进行内存复制 addr.sin_len = sizeof(addr); addr.sin_family = AF_INET; //设置ipv4 addr.sin_port = 0; //表示动态分配端口 addr.sin_addr.s_addr = htonl(INADDR_ANY); //从指定字节缓冲区复制,一个不可变的CFData对象 CFDataRef address = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&addr, sizeof(addr)); //设置socket if (CFSocketSetAddress(sserver, (CFDataRef)address) != kCFSocketSuccess) { fprintf(stderr, "socket绑定失败!\n"); CFRelease(sserver); return NO; } //通过 Bonjour广播服务器时使用 NSData *socketAddressActualData = http://www.mamicode.com/(__bridge NSData *)(CFSocketCopyAddress(sserver)); //转换 socket_in -> socketAddressActual struct sockaddr_in socketAddressActual; memcpy(&socketAddressActual, [socketAddressActualData bytes], [socketAddressActualData length]); self.port = ntohs(socketAddressActual.sin_port); printf("socket listening on port %d\n",self.port); //创建一个RunLoop socket源 CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, sserver, 0); //socket源添加到RunLoop中 CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes); CFRelease(sourceRef); return YES; }-(BOOL)publishService{ _service = [[NSNetService alloc] initWithDomain:@"local." type:@"_tonyipp._tcp" name:@"tony" port:self.port]; //添加服务到当前的RunLoop [_service scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [_service setDelegate:self]; [_service publish]; return YES;}void AcceptCallBack(CFSocketRef socket,CFSocketCallBackType type,CFDataRef address,const void *data,void *info){ CFReadStreamRef readStream = NULL; CFWriteStreamRef writeStream = NULL; //data 参数含义是,如果回调类型是kCFSocketAcceptCallBack,data就是CFSocketNativeHandle类型指针 CFSocketNativeHandle sock = *(CFSocketNativeHandle *)data; //创建读写Socket流 CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock, &readStream, &writeStream); if (!readStream || !writeStream) { close(sock); fprintf(stderr, "创建读写Socket流失败!!!\n"); return; } CFStreamClientContext streamText = {0,NULL,NULL,NULL,NULL}; //注册两种回调函数 CFReadStreamSetClient(readStream, kCFStreamEventHasBytesAvailable, ReadStreamClientCallBack, &streamText); CFWriteStreamSetClient(writeStream, kCFStreamEventCanAcceptBytes, WriteStreamClientCallBack, &streamText); //加入到循环中 CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); CFReadStreamOpen(readStream); CFWriteStreamOpen(writeStream); }void ReadStreamClientCallBack(CFReadStreamRef stream,CFStreamEventType eventType, void *clientCallBackInfo){ uint8 buff[255]; CFReadStreamRef inputStream = stream; if (NULL != inputStream) { CFReadStreamRead(stream, buff, 255); printf("接收数据:%s\n",buff); CFReadStreamUnscheduleFromRunLoop(inputStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); inputStream = NULL; }}void WriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType,void *clientCallBackInfo){ CFWriteStreamRef outputStream = stream; //输出 UInt8 buff[] = "您好,我能够使用Socket了,哈哈哈"; if (NULL != outputStream) { CFWriteStreamWrite(outputStream, buff, strlen((const char *)buff)+1); CFWriteStreamClose(outputStream); CFWriteStreamUnscheduleFromRunLoop(outputStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); outputStream = NULL; } }#pragma mark -NetServiceDelegate--(void)netServiceDidPublish:(NSNetService *)sender{ NSLog(@"netServiceDidPublish"); if ([@"tony" isEqualToString:sender.name]) { if (![sender getInputStream:&_inputStream outputStream:&_outputStream]) { NSLog(@"连接服务器失败"); return; } } }@end
客户端
.h
#include <sys/socket.h>#include <netinet/in.h>#define PORT 49302@interface MViewController : UIViewController<NSStreamDelegate>{ int flag;//操作标志 0为发送 1为接收}@property (weak, nonatomic) IBOutlet UIButton *sendBtn;@property (weak, nonatomic) IBOutlet UIButton *acceptBtn;@property (weak, nonatomic) IBOutlet UILabel *messageLabel;@property(nonatomic,retain)NSInputStream *inputStream;@property(nonatomic,retain)NSOutputStream *outputStream;-(IBAction)sendData:(id)sender;-(IBAction)receiveData:(id)sender;@end
.m
#import "MViewController.h"@interface MViewController ()-(void)initNetworkCommunication;@end@implementation MViewController- (void)viewDidLoad{ [super viewDidLoad]; // Do any additional setup after loading the view from its nib.}-(void)initNetworkCommunication{ CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.1.24", 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];}#pragma mark delegate-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ NSString *event; switch (eventCode) { case NSStreamEventNone: { event = @"None"; } break; case NSStreamEventOpenCompleted: { event = @"OpenCompleted"; } break; case NSStreamEventHasBytesAvailable: { event = @"HasBytesAvailable"; if (flag == 1 && aStream == _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:4]; _messageLabel.text = resultString; } } break; case NSStreamEventHasSpaceAvailable: { event = @"HasSpaceAvailable"; if (flag == 0 && aStream == _outputStream) { //输出 UInt8 buff[] = "您好,能收到我的信息么?"; [_outputStream write:buff maxLength:strlen((const char *)buff) +1]; [_outputStream close]; } } break; case NSStreamEventErrorOccurred: { [self close]; } break; case NSStreamEventEndEncountered: { [self close]; } break; default: { [self close]; } break; }}-(void)close{ [_outputStream close]; [_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [_outputStream setDelegate:nil]; [_inputStream close]; [_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; [_inputStream setDelegate:nil];}@end
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。