zoukankan      html  css  js  c++  java
  • IOS的网络通信的方法 (转)

    ios设备的网络通信的方法,有如下两个大类:

    1、使用socket的方式进行通信。

    2、使用asynsocket类库进行通信。

    两种方法当中,我觉得asynsocket更好,因为是别人已经封装好的类库,比较稳定。但是对于直接使用socket的通信方法我倒是觉得很灵活。因为控制都是自己在做的事情。

    先列举集中不同的使用方法:

    1、直接使用socket的方式。

    以 TCP为利,对于TCP来说,是要区分服务端和客户端的。服务端:通常的方法是服务端启动后监听,是否有客户端连接,如果有连接,则建立与客户端的通信。客户端的方法通常是连接服务端,当连接成功之后,就希望发送数据了。

    客户端:

    CFSocketContext sockContext ;

    CFSocketRef  cfsock ;

     

    sockContext.info = self;

    sockContext.copyDescription = 0;

     

    cfsock = CFSocketCreate(kCFAllocatorDefault,

    PF_INET,

    SOCK_STREAM,

    IPPROTO_TCP,

    kCFSocketConnectCallBack,

    MyCallBack,

    &sockContext

    );

     

     

     

    // 这个地方是个关键的地方,就是建立一个ip地址,然后使的客户端可以向服务端发起连接。

    NSString  *strAddress = @"192.168.1.1";

     

     

     

    if (cfsock != nil) {

     

    struct sockaddr_in addr4; 

     

    memset(&addr4,0,sizeof(addr4));

     

    addr4.sin_len = sizeof(addr4);

     

    addr4.sin_family = AF_INET;

     

    addr4.sin_port = htons(1230);

     

    addr4.sin_addr.s_addr = inet_addr( [strAddress UTF8String] );

     

    CFDataRef address = CFDataCreate(kCFAllocatorDefault, (UInt8*)&addr4, sizeof(addr4));

     

    CFSocketConnectToAddress(cfsock, address, -1);

    }

     

     

    // 发起连接之后,需要将runloop的过程,也就是消息的过程加入到当前线程当中。这样当有事件发生时,会调用对应的方法。

     

    CFRunLoopRef crun = CFRunLoopGetCurrent();// CFRunLoopGetMain();

    CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefaultcfsock0);

     

    CFRunLoopAddSource(crun, source, kCFRunLoopCommonModes);

     

    CFRelease(source);

     

    回调函数:当连接成功之后的处理如下:

     

     

    static void MyCallBack (

    CFSocketRef          s,

    CFSocketCallBackType callbackType,

    CFDataRef    address,

    const void   *data,

    void         *info

    )

    {

     

    if (data!=NULL) {

    NSLog(@"传输失败!");

    }

     

    SocketTestAppDelegate *client = (SocketTestAppDelegate*)info;

     

    [client performSelectoInBackground:@selector(readstreamwithObject:nil];

     

     

    }

     

    -(void) readstream

    {

    char buffer[1024];

     

    NSAutoreleasePool *pool = [[NSAutoreleasePool allocinit];

     

    while (recv(CFSocketGetNative(cfsock),buffer,sizeof(buffer),0)) {

     

    }

     

    [pool release];

    }

    //  如果希望直接向服务器写内容的话,采用如下的方法。

    -(void) sendstream

    {

    NSString * stringtosend = @"hello everyone";

     

    const char *data = [stringtosend UTF8String];

     

    send(CFSocketGetNative(cfsock),data,strlen(data)+1,0);

    }

     

    服务器端的程序:

     

     

    CFSocketRef socketserver;

    int setupSocket()

    {

    socketserver =CFSocketCreate(kCFAllocatorDefault,PF_INET,SOCK_STREAM,IPPROTO_TCP,kCFSocketAcceptCallBack,myaccept,NULL);

     

    int optval =1;

     

    setsockopt(CFSocketGetNative(socketserver), SOL_SOCKETSO_REUSEADDR, (void*)&optval,sizeof(optval));

     

    struct sockaddr_in addr4;

     

    memset(&addr4,0,sizeof(addr4));

     

    addr4.sin_len = sizeof(addr4);

     

    addr4.sin_family = AF_INET;

     

    addr4.sin_port = htons(10);

    addr4.sin_addr.s_addr=htonl(INADDR_ANY);

     

    CFDataRef  address = CFDataCreate(kCFAllocatorDefault, (UInt8*)&addr4, sizeof(addr4));

     

    CFSocketSetAddress(socketserver, address);

     

    CFRunLoopRef cfRunloop = CFRunLoopGetCurrent();

     

    CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefaultsocketserver0);

     

    CFRunLoopAddSource(cfRunloop, source, kCFRunLoopCommonModes);

     

    CFRelease(source);

     

    }

     

    //服务端的socket建立之后,就需要接受client的连接,因此建立连接的回调函数。

     

     

    static void myaccept (

    CFSocketRef          s,

    CFSocketCallBackType callbackType,

    CFDataRef    address,

    const void   *data,

    void         *info

    )

    {

     

    if (callbackType == kCFSocketAcceptCallBack) {

     

     

    // 如果对端连接成功的话,是可以获取对端的名称和socket的。

     

    CFSocketNativeHandle nativesockethandle = *(CFSocketNativeHandle*)data;

     

    uint8_t name[100];

    socklen_t namelen = 100;

     

    getpeername(nativesockethandle, (struct sockaddr *)name, &namelen);

     

    //除此以外,更重要的是获取输入流 和 输出流,

     

    CFReadStreamRef iStream;

    CFWriteStreamRef oStream;

     

    // 创建一个可读写的socket连接

     

     

    CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativesockethandle, &iStream, &oStream);

     

    CFStreamClientContext streamcontext={

    0,NULL,NULL,NULL

    };

    // 注册两种事件!

     

    CFReadStreamSetClient(iStream, kCFStreamEventHasBytesAvailable, readStream, &streamcontext);

     

    CFReadStreamSetClient(iStream, kCFStreamEventCanAcceptBytes, writeStream, &streamcontext);

     

    //加入到循环当中!

     

    CFReadStreamScheduleWithRunLoop(iStream, CFRunLoopGetCurrent(),kCFRunLoopCommonModes);

     

    CFWriteStreamScheduleWithRunLoop(oStream, CFRunLoopGetCurrent(),kCFRunLoopCommonModes);

     

     

    CFReadStreamOpen(iStream);

     

    CFWriteStreamOpen(oStream);

    }

     

     

    }

     

     

     

    void readStream(CFReadStreamRef stream,CFStreamEventType eventType, void *clientCallBackInfo) {

     

        UInt8 buff[255];

     

        CFReadStreamRead(stream, buff, 255);

     

        printf("received: %s", buff);

     

    }

     

    void writeStream (CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) {

     

       // outputStream = stream;

     

     

     

       char *str = "nihao";
    CFWriteStreamWrite(outputStream, str, strlen(line) + 1);
    
    
    

    }

     

    另一种方法是使用NSStream的方式构建客户端,然后发送和接受内容。

     

     

    -(void)startClient
    {
        host = [NSHosthostWithAddress:@"192.168.201.24"];//hostWithName:@"www.apple.com"];
        [NSStreamgetStreamsToHost:host port:4242 inputStream:&inStream outputStream:&outStream];
         
        if((inStream == nil) || (outStream == nil))
        {
            NSLog(@"Error: Failed to create streams!") ;
            [selfrelease];
        }
    }
     
    - (void)stream:(NSStream*)aStream handleEvent:(NSStreamEvent)eventCode
    {
        switch(eventCode) {
            caseNSStreamEventHasBytesAvailable:
            {
                NSMutableData*input = [[NSMutableDataalloc] init];
                uint8_t buffer[1024];
                intlen;
                while([inStream hasBytesAvailable])
                {
                    len = [inStream read:buffer maxLength:sizeof(buffer)];
                    if(len > 0)
                    {
                        [input appendBytes:buffer length:len];
                    }
                }
                self._resultdata = input;
                self._resultstring = [[NSStringalloc] initWithData:input encoding:NSUTF8StringEncoding];
                [input release];
                break;
            }
            caseNSStreamEventEndEncountered:
                [selfcloseStream];
                break;
            caseNSStreamEventHasSpaceAvailable:
            caseNSStreamEventErrorOccurred:
            {
                NSLog(@"Error:%@:%@",[[aStream streamError] code], [[aStream streamError] localizedDescription]);
            }
            caseNSStreamEventOpenCompleted:
            caseNSStreamEventNone:
            default:
                break;
        }
    }
     
    -(void)closeStream{
        [inStream close];
        [outStream close];
        [inStream removeFromRunLoop:[NSRunLoopcurrentRunLoop] forMode:NSDefaultRunLoopMode];
        [outStream removeFromRunLoop:[NSRunLoopcurrentRunLoop] forMode:NSDefaultRunLoopMode];
        [inStream setDelegate:nil];
        [outStream setDelegate:nil];
        [inStream release];
        [outStream release];
        inStream = nil;
        outStream = nil;
    }
     
    -(void)openStream{
        [inStream retain];
        [outStream retain];
        [inStream setProperty:NSStreamSocketSecurityLevelSSLv3forKey:NSStreamSocketSecurityLevelKey];
        [outStream setProperty:NSStreamSocketSecurityLevelSSLv3forKey:NSStreamSocketSecurityLevelKey];
        NSMutableDictionary* sslSettings;
        sslSettings = [NSMutableDictionarydictionaryWithObjectsAndKeys:(id)kCFBooleanFalse,kCFStreamSSLValidatesCertificateChain,kCFBooleanFalse,kCFStreamSSLIsServer,nil];
        CFWriteStreamSetProperty((CFWriteStreamRef)outStream, kCFStreamPropertySSLSettings, sslSettings);
        [inStream setDelegate:self];
        [outStream setDelegate:self];
        [inStream scheduleInRunLoop:[NSRunLoopcurrentRunLoop] forMode:NSDefaultRunLoopMode];
        [outStream scheduleInRunLoop:[NSRunLoopcurrentRunLoop] forMode:NSDefaultRunLoopMode];
        [inStream open];
        [outStream open];
    }
     
    -(int)writeString: (NSString*) string
    {
        NSData*messageAsData = [string dataUsingEncoding:NSASCIIStringEncoding];
        return[outStream write: (c*****t uint8_t *) [messageAsData bytes] maxLength: [messageAsData length]];
    }
     
    -(int)writeBytes: (char*) buffer length: (unsigned int) len
    {
        return[outStream write: (c*****t uint8_t *) buffer maxLength: len];
    }
    @end
  • 相关阅读:
    Test
    占位2
    开坑纪念
    function 类型(函数定义)----读书总结
    css位元素 after
    算法-哈希表
    CF547D
    CF538H
    CF516D
    CF505E
  • 原文地址:https://www.cnblogs.com/worldtraveler/p/2830766.html
Copyright © 2011-2022 走看看