xingfudeyutian 2014-11-25 08:25 采纳率: 0%
浏览 2013

问一个笼统的问题,ios客户端和服务器通信都有什么方法

ios客户端和服务器通信时
都有那些方法?那种比较好用或最常用的?

  • 写回答

3条回答 默认 最新

  • threenewbee 2014-11-25 09:43
    关注

    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(kCFAllocatorDefault, cfsock, 0);

    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(readstream) withObject:nil];

    }

    -(void) readstream

    {

    char buffer[1024];

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    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_SOCKET, SO_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(kCFAllocatorDefault, socketserver, 0);

    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

    转自:http://blog.csdn.net/dongdongdongjl/article/details/7776377

    评论

报告相同问题?

悬赏问题

  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题