socket编程---之多连接服务端实现(CFNetwork框架)

来源:互联网 发布:中小学课本同步软件 编辑:程序博客网 时间:2024/06/05 08:16
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/fcntl.h>#include <sys/select.h>#include <sys/time.h>#include <sys/ioctl.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <string.h>#include <sys/errno.h>#import <CFNetwork/CFNetwork.h>#import <Foundation/Foundation.h>CFReadStreamRef  readStream;CFWriteStreamRef writeStream;// --读取接收缓冲区的回调函数 当CFReadStreamRef有可读的数据或者发送其它事件时该函数由系统自动调用static void readStreamCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) {    switch (eventType) {        case kCFStreamEventHasBytesAvailable:        {            UInt8 buff[255];            if(CFReadStreamRead(stream, buff, 255) > 0  ){                NSLog(@"接收到的数据为:%s",buff);                                UInt8 sendbuff[255] = "hello!";                CFIndex bytesToSend = CFWriteStreamWrite(writeStream, sendbuff, sizeof(buff));                if(bytesToSend > 0){                    NSLog(@"像客户端发送数据成功...");                }else if (bytesToSend == 0){                    NSLog(@"writeStream 已满,无法写入数据....");                }else{                    NSLog(@"发送出错");                }            }else{                NSLog(@"没有数据了....");            }        }        default:        {            if (eventType == kCFStreamEventEndEncountered) {                NSLog(@"接收缓存区中没有数据了....");            }else if (eventType == kCFStreamEventErrorOccurred){                NSLog(@"出错了....");            }                    }            break;    }}// --向客户端写数据的回调函数 仅当调用CFWriteStreamWrite()函数时该函数才被调用.static void writeStreamCallBack(CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) {    switch (eventType) {        case kCFStreamEventCanAcceptBytes:{                         break;        }        default:            break;    }    }// --等待客户端连接的回调函数static void serverSocketCallBack(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info){    if ( type != kCFSocketAcceptCallBack ) {        return;    }            CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle*)data; // --客户端连接的socket信息    struct sockaddr_in client_add;    socklen_t clientLen = sizeof(client_add);    if (getpeername(nativeSocketHandle, (struct sockaddr *)&client_add, &clientLen) == -1) {        perror("getpeername()");        exit(0);    }    NSString *ip = [[NSString alloc] initWithCString:inet_ntoa(client_add.sin_addr) encoding:NSASCIIStringEncoding];    NSString *port = [NSString stringWithFormat:@"%d",client_add.sin_port];    NSLog(@"连接的客户端为:%@%@",ip,port);            // --4.创建和客户端socket的读写缓存    CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream, &writeStream);    if (readStream && writeStream) {        CFStreamClientContext streamContext = {0,NULL, NULL, NULL}; // --一个标记CFStreamRead/Write的上下文        if (!CFReadStreamSetClient(readStream, kCFStreamEventHasBytesAvailable,readStreamCallBack,&streamContext)){ // --设置接收缓存区的回调函数            exit(1);        }                if (!CFWriteStreamSetClient(writeStream, kCFStreamEventCanAcceptBytes, writeStreamCallBack, &streamContext)){ // --设置发送缓冲区的回调函数            exit(1);        }                CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);  // --将readStream加入runloop,这样才可以不停的读取数据        CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); // --将writeStream加入runloop,这样才可以不停的发送数据        CFReadStreamOpen(readStream);   // --打开readStream才会工作        CFWriteStreamOpen(writeStream); // --打开writeStream才会工作        } else {        close(nativeSocketHandle);    }}int main(int argc, const char * argv[]) {    @autoreleasepool {        // --1.创建服务器端socket        CFSocketContext socketContext = {0,NULL,NULL,NULL};        CFSocketRef serverSocket = CFSocketCreate(kCFAllocatorDefault, AF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, serverSocketCallBack, &socketContext);        if (serverSocket == NULL) {            perror("create socket");            exit(0);        }                // --2.绑定并监听某个地址        struct sockaddr_in socketAddress;        memset(&socketAddress, 0, sizeof(socketAddress));        socketAddress.sin_len = sizeof(socketAddress);        socketAddress.sin_family = AF_INET;        socketAddress.sin_port = htons(2125);        socketAddress.sin_addr.s_addr = htonl(INADDR_ANY);        NSData *addressData = [NSData dataWithBytes:&socketAddress length:sizeof(socketAddress)];        if (CFSocketSetAddress(serverSocket, (__bridge CFDataRef)addressData) != kCFSocketSuccess) {            perror("bind && listen");            if (serverSocket != NULL) {                CFRelease(serverSocket);                serverSocket = NULL;            }        }                // --3.添加到runloop中,等待连接请求,这里默认的实现是可以接收多个客户端的连接        CFRunLoopRef currentRunloop = CFRunLoopGetCurrent();        if (serverSocket == NULL) {            exit(0);        }        CFRunLoopSourceRef runloopSourse = CFSocketCreateRunLoopSource(NULL, serverSocket, 0);        CFRunLoopAddSource(currentRunloop, runloopSourse, kCFRunLoopDefaultMode);        CFRunLoopRun();    }    return 0;}

0 0
原创粉丝点击