首页 > 代码库 > 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